src/cm/models.py
author Production Moz <dev@sopinspace.com>
Wed, 26 Jun 2013 19:25:09 +0200
changeset 514 f99c7f7401b0
parent 513 60da0b2cca9f
child 515 0be906e586e6
permissions -rw-r--r--
Reorder classes in models.py.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
156
6d447220fd1e bug fix: removed \r in textversion's content because of a comment position bug in pre_edit. Added a save function to TextVersion to do so.
rbernard
parents: 155
diff changeset
     1
import re
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
     2
from cm.converters.pandoc_converters import \
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
     3
    CHOICES_INPUT_FORMATS as CHOICES_INPUT_FORMATS_PANDOC, \
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
     4
    DEFAULT_INPUT_FORMAT as DEFAULT_INPUT_FORMAT_PANDOC, pandoc_convert
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
     5
from cm.models_base import PermanentModel, KeyManager, Manager, KeyModel, AuthorModel
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
     6
from cm.models_utils import *
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
     7
from cm.utils.dj import absolute_reverse
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
     8
from cm.utils.date import datetime_to_user_str
175
4f072edc51a1 BUG FIX : handling html
rbernard
parents: 160
diff changeset
     9
from cm.utils.html import on_content_receive
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    10
from cm.utils.comment_positioning import compute_new_comment_positions
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    11
from django import forms
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    12
from django.db.models import Q
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    13
from django.template.loader import render_to_string
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    14
from django.conf import settings
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    15
from django.template import RequestContext
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    16
from django.contrib.auth.models import Permission
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    17
from django.contrib.contenttypes import generic
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    18
from django.contrib.contenttypes.models import ContentType
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    19
from django.core.files.base import ContentFile
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    20
from django.core.urlresolvers import reverse
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    21
from django.template.defaultfilters import timesince
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    22
from django.db import models
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    23
from django.utils.translation import ugettext as _, ugettext_lazy, ugettext_noop
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    24
from tagging.fields import TagField
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    25
import pickle
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    26
from django.db import connection
72
b0c777412d0a keep comment dates (created / modified) when duplicating (fixes #12)
raph
parents: 38
diff changeset
    27
from datetime import datetime
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    28
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    29
class TextManager(Manager):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    30
    def create_text(self, title, format, content, note, name, email, tags, user=None, state='approved', **kwargs):
175
4f072edc51a1 BUG FIX : handling html
rbernard
parents: 160
diff changeset
    31
        content = on_content_receive(content, format)
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    32
        text = self.create(name=name, email=email, user=user, state=state)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    33
        text_version = TextVersion.objects.create(title=title, format=format, content=content, text=text, note=note, name=name, email=email, tags=tags, user=user)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    34
        return text
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    35
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    36
    def create_new_version(self, text, title, format, content, note, name, email, tags, user=None, **kwargs):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    37
        text_version = TextVersion.objects.create(title=title, format=format, content=content, text=text, note=note, name=name, email=email, tags=tags, user=user)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    38
        return text_version
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    39
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    40
class Text(PermanentModel, AuthorModel):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    41
    modified = models.DateTimeField(auto_now=True)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    42
    created = models.DateTimeField(auto_now_add=True)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    43
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    44
    private_feed_key = models.CharField(max_length=20, db_index=True, unique=True, blank=True, null=True, default=None)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    45
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    46
    # denormalized fields
407
2d14a80716e2 When last_version is deleted, do not delete text and previous versions in cascade, but really delete text only when there is no previous version, otherwise update text.last_version with previous version.
gibus
parents: 347
diff changeset
    47
    last_text_version = models.ForeignKey("TextVersion", related_name='related_text', null=True, blank=True, on_delete=models.SET_NULL)
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    48
    title = models.TextField()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    49
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    50
    objects = TextManager()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    51
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    52
    def get_latest_version(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    53
        return self.last_text_version
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    54
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    55
    def fetch_latest_version(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    56
        versions = self.get_versions()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    57
        if versions:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    58
            return versions[0]
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    59
        else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    60
            return None
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    61
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    62
    def update_denorm_fields(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    63
        real_last_text_version = self.fetch_latest_version()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    64
    
289
285e67006eb0 fix error when last text_version is deleted
raph
parents: 266
diff changeset
    65
        try:
285e67006eb0 fix error when last text_version is deleted
raph
parents: 266
diff changeset
    66
            last_text_version = self.last_text_version
285e67006eb0 fix error when last text_version is deleted
raph
parents: 266
diff changeset
    67
        except TextVersion.DoesNotExist:
285e67006eb0 fix error when last text_version is deleted
raph
parents: 266
diff changeset
    68
            # the text version has just been deleted
285e67006eb0 fix error when last text_version is deleted
raph
parents: 266
diff changeset
    69
            last_text_version = None
285e67006eb0 fix error when last text_version is deleted
raph
parents: 266
diff changeset
    70
            
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    71
        modif = False
289
285e67006eb0 fix error when last text_version is deleted
raph
parents: 266
diff changeset
    72
        if real_last_text_version and real_last_text_version != last_text_version:
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    73
            self.last_text_version = real_last_text_version
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    74
            modif = True
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    75
            
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    76
        if real_last_text_version and real_last_text_version.title and real_last_text_version.title != self.title:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    77
            self.title = real_last_text_version.title
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    78
            modif = True
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    79
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    80
        if real_last_text_version and real_last_text_version.modified != self.modified:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    81
            self.modified = real_last_text_version.modified
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    82
            modif = True
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    83
            
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    84
        if modif:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    85
            self.save()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    86
407
2d14a80716e2 When last_version is deleted, do not delete text and previous versions in cascade, but really delete text only when there is no previous version, otherwise update text.last_version with previous version.
gibus
parents: 347
diff changeset
    87
        # GIB: there is no more version for this text => delete it
2d14a80716e2 When last_version is deleted, do not delete text and previous versions in cascade, but really delete text only when there is no previous version, otherwise update text.last_version with previous version.
gibus
parents: 347
diff changeset
    88
        if real_last_text_version == None and last_text_version == None:
2d14a80716e2 When last_version is deleted, do not delete text and previous versions in cascade, but really delete text only when there is no previous version, otherwise update text.last_version with previous version.
gibus
parents: 347
diff changeset
    89
          self.real_delete()
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    90
                
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    91
    def get_title(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    92
        return self.get_latest_version().title
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    93
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    94
    def get_versions(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    95
        """
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    96
        Versions with most recent first
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    97
        """
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    98
        versions = TextVersion.objects.filter(text__exact=self).order_by('-created')
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    99
        # TODO: use new postgresql 8.4 row_number as extra select to do that
145
fb5b1e6ad179 refactor version explorer
raph
parents: 140
diff changeset
   100
        #for index in xrange(len(versions)):
fb5b1e6ad179 refactor version explorer
raph
parents: 140
diff changeset
   101
        #    v = versions[index]
fb5b1e6ad179 refactor version explorer
raph
parents: 140
diff changeset
   102
        #    # version_number is 1-based
fb5b1e6ad179 refactor version explorer
raph
parents: 140
diff changeset
   103
        #    setattr(v, 'version_number', len(versions) - index)
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   104
        return versions
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   105
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   106
    def get_version(self, version_number):        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   107
        """
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   108
        Get version number 'version_number' (1-based)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   109
        """
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   110
        version = TextVersion.objects.filter(text__exact=self).order_by('created')[version_number - 1:version_number][0]
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   111
        return version
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   112
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   113
    def get_inversed_versions(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   114
        versions = TextVersion.objects.filter(text__exact=self).order_by('created')
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   115
        # TODO: use new postgresql 8.4 row_number as extra select to do that
145
fb5b1e6ad179 refactor version explorer
raph
parents: 140
diff changeset
   116
        #for index in xrange(len(versions)):
fb5b1e6ad179 refactor version explorer
raph
parents: 140
diff changeset
   117
        #    v = versions[index]
fb5b1e6ad179 refactor version explorer
raph
parents: 140
diff changeset
   118
        #    # version_number is 1-based
fb5b1e6ad179 refactor version explorer
raph
parents: 140
diff changeset
   119
        #    setattr(v, 'version_number', index + 1)
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   120
        return versions
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   121
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   122
    def get_versions_number(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   123
        return self.get_versions().count()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   124
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   125
    def is_admin(self, adminkey=None):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   126
        if adminkey and self.adminkey == adminkey:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   127
            return True
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   128
        else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   129
            return False
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   130
145
fb5b1e6ad179 refactor version explorer
raph
parents: 140
diff changeset
   131
    def revert_to_version(self, text_version_key):
fb5b1e6ad179 refactor version explorer
raph
parents: 140
diff changeset
   132
        text_version = TextVersion.objects.get(key=text_version_key)
fb5b1e6ad179 refactor version explorer
raph
parents: 140
diff changeset
   133
        if text_version.text != self:
fb5b1e6ad179 refactor version explorer
raph
parents: 140
diff changeset
   134
            raise Exception('Invalid revert attempt')
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   135
        new_text_version = TextVersion.objects.duplicate(text_version, True)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   136
        return new_text_version
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   137
        
103
61fd17f9ab78 enh: detached comments
rbernard
parents: 72
diff changeset
   138
    def edit(self, new_title, new_format, new_content, new_tags=None, new_note=None, keep_comments=True, cancel_modified_scopes=True, new_version=True):
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   139
        text_version = self.get_latest_version()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   140
            
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   141
        if new_version:        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   142
            text_version = TextVersion.objects.duplicate(text_version, keep_comments)
103
61fd17f9ab78 enh: detached comments
rbernard
parents: 72
diff changeset
   143
        text_version.edit(new_title, new_format, new_content, new_tags, new_note, keep_comments, cancel_modified_scopes)        
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   144
        return text_version 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   145
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   146
    def __unicode__(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   147
        return self.title    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   148
514
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   149
DEFAULT_INPUT_FORMAT = getattr(settings, 'DEFAULT_INPUT_FORMAT', DEFAULT_INPUT_FORMAT_PANDOC)
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   150
CHOICES_INPUT_FORMATS = getattr(settings, 'CHOICES_INPUT_FORMATS', CHOICES_INPUT_FORMATS_PANDOC)
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   151
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   152
class TextVersionManager(KeyManager):
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   153
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   154
    def duplicate(self, text_version, duplicate_comments=True):
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   155
        old_comment_set = set(text_version.comment_set.all())
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   156
        text_version.id = None
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   157
        
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   158
        # generate new key
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   159
        text_version.key = self._gen_key()
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   160
        text_version.adminkey = self._gen_adminkey()
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   161
        
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   162
        text_version.save()
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   163
        
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   164
        duplicate_text_version = text_version
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   165
        
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   166
        if duplicate_comments:
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   167
            old_comment_map = {}
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   168
            while len(old_comment_set):
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   169
                for c in old_comment_set:
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   170
                    if not c.reply_to or c.reply_to.id in old_comment_map:
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   171
                        old_id = c.id
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   172
                        old_comment_set.remove(c)
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   173
                        reply_to = None
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   174
                        if c.reply_to:                            
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   175
                            reply_to = old_comment_map[c.reply_to.id]  
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   176
                        c2 = Comment.objects.duplicate(c, duplicate_text_version, reply_to, keep_dates=True)
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   177
                        old_comment_map[old_id] = c2
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   178
                        break
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   179
                 
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   180
        return duplicate_text_version
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   181
        
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   182
class TextVersion(AuthorModel, KeyModel):
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   183
    modified = models.DateTimeField(auto_now=True)
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   184
    created = models.DateTimeField(auto_now_add=True)
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   185
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   186
    title = models.TextField(ugettext_lazy("Title"))
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   187
    format = models.CharField(ugettext_lazy("Format"), max_length=20, blank=False, default=DEFAULT_INPUT_FORMAT, choices=CHOICES_INPUT_FORMATS)
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   188
    content = models.TextField(ugettext_lazy("Content"))
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   189
    tags = TagField(ugettext_lazy("Tags"), max_length=1000)
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   190
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   191
    note = models.CharField(ugettext_lazy("Note"), max_length=100, null=True, blank=True)
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   192
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   193
    mod_posteriori = models.BooleanField(ugettext_lazy('Moderation a posteriori?'), default=True)
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   194
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   195
    from django.utils.safestring import mark_safe
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   196
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   197
    category_1 = models.CharField(ugettext_lazy("Label for the first category of comments"), help_text=mark_safe(_("Paragraphs including at least one comment of this category will have a vertical bar with this color: ") + '<span style="width: 2px; height: 5px; background-color: #1523f4">&nbsp;</span><br />' + _("Leave blank to use the value configured for the workspace.") + '<br />' + _("To disable this category for this text whatever the configuration for the workspace, enter: ") + '<em>none</em>'), max_length=20, null=True, blank=True)
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   198
    category_2 = models.CharField(ugettext_lazy("Label for the second category of comments"), help_text=mark_safe(_("Paragraphs including at least one comment of this category will have a vertical bar with this color: ") + '<span style="width: 2px; height: 5px; background-color: #f4154f">&nbsp;</span><br />' + _("Leave blank to use the value configured for the workspace. ") + '<br />' + _("To disable this category for this text whatever the configuration for the workspace, enter: ") + '<em>none</em>'), max_length=20, null=True, blank=True)
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   199
    category_3 = models.CharField(ugettext_lazy("Label for the third category of comments"), help_text=mark_safe(_("Paragraphs including at least one comment of this category will have a vertical bar with this color: ") + '<span style="width: 2px; height: 5px; background-color: #09ff09">&nbsp;</span><br />' + _("Leave blank to use the value configured for the workspace. ") + '<br />' + _("To disable this category for this text whatever the configuration for the workspace, enter: ") + '<em>none</em>'), max_length=20, null=True, blank=True)
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   200
    category_4 = models.CharField(ugettext_lazy("Label for the fourth category of comments"), help_text=mark_safe(_("Paragraphs including at least one comment of this category will have a vertical bar with this color: ") + '<span style="width: 2px; height: 5px; background-color: #bc39cf">&nbsp;</span><br />' + _("Leave blank to use the value configured for the workspace. ") + '<br />' + _("To disable this category for this text whatever the configuration for the workspace, enter: ") + '<em>none</em>'), max_length=20, null=True, blank=True)
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   201
    category_5 = models.CharField(ugettext_lazy("Label for the fifth category of comments"), help_text=mark_safe(_("Paragraphs including at least one comment of this category will have a vertical bar with this color: ") + '<span style="width: 2px; height: 5px; background-color: #ffbd08">&nbsp;</span><br />' + _("Leave blank to use the value configured for the workspace. ") + '<br />' + _("To disable this category for this text whatever the configuration for the workspace, enter: ") + '<em>none</em>'), max_length=20, null=True, blank=True)
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   202
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   203
    text = models.ForeignKey("Text")
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   204
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   205
    objects = TextVersionManager()
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   206
    
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   207
    def get_content(self, format='html'):
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   208
        return pandoc_convert(self.content, self.format, format)
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   209
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   210
    def get_comments(self):
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   211
        "Warning: data access without security"
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   212
        return self.comment_set.filter(reply_to=None, deleted=False)
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   213
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   214
    def get_replies(self):
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   215
        "Warning: data access without security"
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   216
        return self.comment_set.filter(~Q(reply_to == None), Q(deleted=False))
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   217
    
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   218
    def __unicode__(self):
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   219
        return '<%d> %s' % (self.id, self.title)    
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   220
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   221
    def edit(self, new_title, new_format, new_content, new_tags=None, new_note=None, keep_comments=True, cancel_modified_scopes=True):
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   222
        new_content = on_content_receive(new_content, new_format) 
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   223
        if not keep_comments :
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   224
            self.comment_set.all().delete()
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   225
        elif self.content != new_content or new_format != self.format:
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   226
            comments = self.get_comments() ;
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   227
            tomodify_comments, toremove_comments = compute_new_comment_positions(self.content, self.format, new_content, new_format, comments)
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   228
            [comment.save(keep_dates=True) for comment in tomodify_comments]
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   229
            if cancel_modified_scopes :
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   230
                [comment.remove_scope() for comment in toremove_comments]
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   231
            else :
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   232
                [comment.delete() for comment in toremove_comments]
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   233
                
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   234
        self.title = new_title
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   235
        if new_tags:
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   236
            self.tags = new_tags
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   237
        if new_note:
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   238
            self.note = new_note
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   239
        self.content = new_content
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   240
        self.format = new_format
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   241
        self.save()
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   242
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   243
    def get_next_version(self):        
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   244
        other_versions = TextVersion.objects.filter(text__exact=self.text).order_by('created').filter(created__gt=self.created)
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   245
        return other_versions[0] if other_versions else None 
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   246
        if other_versions:
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   247
            return 
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   248
        else:
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   249
            return None
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   250
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   251
    def get_previous_version(self):
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   252
        other_versions = TextVersion.objects.filter(text__exact=self.text).order_by('-created').filter(created__lt=self.created)
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   253
        return other_versions[0] if other_versions else None
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   254
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   255
    def get_version_number(self):
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   256
        return TextVersion.objects.filter(text__exact=self.text).order_by('created').filter(created__lte=self.created).count()
f99c7f7401b0 Reorder classes in models.py.
Production Moz <dev@sopinspace.com>
parents: 513
diff changeset
   257
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   258
class CommentManager(Manager):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   259
    
72
b0c777412d0a keep comment dates (created / modified) when duplicating (fixes #12)
raph
parents: 38
diff changeset
   260
    def duplicate(self, comment, text_version, reply_to=None, keep_dates=False):
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   261
        comment.id = None
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   262
        comment.text_version = text_version
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   263
        if reply_to:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   264
            comment.reply_to = reply_to
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   265
        self.update_keys(comment)
72
b0c777412d0a keep comment dates (created / modified) when duplicating (fixes #12)
raph
parents: 38
diff changeset
   266
        comment.save(keep_dates=keep_dates)
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   267
        return comment
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   268
    
130
f257ad33bed5 model change+migration (add id_key to comment): run ./bin/django migrate
raph
parents: 103
diff changeset
   269
from cm.models_base import KEY_MAX_SIZE, generate_key
f257ad33bed5 model change+migration (add id_key to comment): run ./bin/django migrate
raph
parents: 103
diff changeset
   270
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   271
class Comment(PermanentModel, AuthorModel):
72
b0c777412d0a keep comment dates (created / modified) when duplicating (fixes #12)
raph
parents: 38
diff changeset
   272
    modified = models.DateTimeField()
b0c777412d0a keep comment dates (created / modified) when duplicating (fixes #12)
raph
parents: 38
diff changeset
   273
    created = models.DateTimeField()
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   274
130
f257ad33bed5 model change+migration (add id_key to comment): run ./bin/django migrate
raph
parents: 103
diff changeset
   275
    # key to identify same comments across versions
f257ad33bed5 model change+migration (add id_key to comment): run ./bin/django migrate
raph
parents: 103
diff changeset
   276
    id_key = models.CharField(max_length=KEY_MAX_SIZE, db_index=True, default=generate_key)
f257ad33bed5 model change+migration (add id_key to comment): run ./bin/django migrate
raph
parents: 103
diff changeset
   277
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   278
    text_version = models.ForeignKey("TextVersion")
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   279
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   280
    # comment_set will be replies
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   281
    reply_to = models.ForeignKey("Comment", null=True, blank=True)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   282
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   283
    title = models.TextField()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   284
    content = models.TextField()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   285
    content_html = models.TextField()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   286
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   287
    format = models.CharField(_("Format:"), max_length=20, blank=False, default=DEFAULT_INPUT_FORMAT, choices=CHOICES_INPUT_FORMATS)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   288
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   289
    tags = TagField()
504
b2e0186daa5b Adds a category to comments, painted with colored vertical bar.
gibus
parents: 478
diff changeset
   290
b2e0186daa5b Adds a category to comments, painted with colored vertical bar.
gibus
parents: 478
diff changeset
   291
    category = models.PositiveSmallIntegerField(default=0)
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   292
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   293
    start_wrapper = models.IntegerField(null=True, blank=True)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   294
    end_wrapper = models.IntegerField(null=True, blank=True)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   295
    start_offset = models.IntegerField(null=True, blank=True)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   296
    end_offset = models.IntegerField(null=True, blank=True)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   297
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   298
    objects = CommentManager()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   299
    
327
d858c3bb07fe save prototype for django new version (1.2.3)
gibus
parents: 305
diff changeset
   300
    def save(self, keep_dates=False, **kwargs):
72
b0c777412d0a keep comment dates (created / modified) when duplicating (fixes #12)
raph
parents: 38
diff changeset
   301
        if not keep_dates:
b0c777412d0a keep comment dates (created / modified) when duplicating (fixes #12)
raph
parents: 38
diff changeset
   302
            now = datetime.now()
b0c777412d0a keep comment dates (created / modified) when duplicating (fixes #12)
raph
parents: 38
diff changeset
   303
            if not self.id: 
b0c777412d0a keep comment dates (created / modified) when duplicating (fixes #12)
raph
parents: 38
diff changeset
   304
                self.created = now  
b0c777412d0a keep comment dates (created / modified) when duplicating (fixes #12)
raph
parents: 38
diff changeset
   305
            self.modified = now 
327
d858c3bb07fe save prototype for django new version (1.2.3)
gibus
parents: 305
diff changeset
   306
        super(PermanentModel, self).save(**kwargs) 
72
b0c777412d0a keep comment dates (created / modified) when duplicating (fixes #12)
raph
parents: 38
diff changeset
   307
            
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   308
    def __unicode__(self):
262
9644e27ad08d fix comment __str__ display
raph
parents: 259
diff changeset
   309
        return '<%d> %s [st_wrp:%s, st_ofs:%s, e_wrp:%s, e_ofs:%s]' % (self.id, self.title,  self.start_wrapper ,  self.start_offset,  self.end_wrapper,  self.end_offset, )    
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   310
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   311
    def is_reply(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   312
        return self.reply_to != None
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   313
    
16
036705244cab FIX: comment visibility takes ownership into account
raph
parents: 12
diff changeset
   314
    def is_thread_full_visible(self, own_user=None):
036705244cab FIX: comment visibility takes ownership into account
raph
parents: 12
diff changeset
   315
        """
036705244cab FIX: comment visibility takes ownership into account
raph
parents: 12
diff changeset
   316
        own_user: comment belonging to this user are also visible 
036705244cab FIX: comment visibility takes ownership into account
raph
parents: 12
diff changeset
   317
        """
036705244cab FIX: comment visibility takes ownership into account
raph
parents: 12
diff changeset
   318
        if self.state == 'approved' or (own_user and self.user == own_user):
036705244cab FIX: comment visibility takes ownership into account
raph
parents: 12
diff changeset
   319
            if self.reply_to==None:
036705244cab FIX: comment visibility takes ownership into account
raph
parents: 12
diff changeset
   320
                return True
036705244cab FIX: comment visibility takes ownership into account
raph
parents: 12
diff changeset
   321
            else:                
036705244cab FIX: comment visibility takes ownership into account
raph
parents: 12
diff changeset
   322
                return self.reply_to.is_thread_full_visible(own_user)
036705244cab FIX: comment visibility takes ownership into account
raph
parents: 12
diff changeset
   323
        return False
036705244cab FIX: comment visibility takes ownership into account
raph
parents: 12
diff changeset
   324
               
103
61fd17f9ab78 enh: detached comments
rbernard
parents: 72
diff changeset
   325
    def is_scope_removed(self):
61fd17f9ab78 enh: detached comments
rbernard
parents: 72
diff changeset
   326
        #when scope is "removed" we will have 
61fd17f9ab78 enh: detached comments
rbernard
parents: 72
diff changeset
   327
        #self.start_wrapper == self.end_wrapper == self.start_offset == self.end_offset == -1
61fd17f9ab78 enh: detached comments
rbernard
parents: 72
diff changeset
   328
        return (self.start_wrapper == -1)  
61fd17f9ab78 enh: detached comments
rbernard
parents: 72
diff changeset
   329
               
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   330
    def top_comment(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   331
        if self.reply_to == None :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   332
            return self
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   333
        else : 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   334
            return self.reply_to.top_comment()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   335
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   336
    def depth(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   337
        if self.reply_to == None :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   338
            return 0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   339
        else : 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   340
            return 1 + self.reply_to.depth()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   341
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   342
    def delete(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   343
        PermanentModel.delete(self)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   344
        # delete replies
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   345
        [c.delete() for c in self.comment_set.all()]
103
61fd17f9ab78 enh: detached comments
rbernard
parents: 72
diff changeset
   346
        
61fd17f9ab78 enh: detached comments
rbernard
parents: 72
diff changeset
   347
    def remove_scope(self):
61fd17f9ab78 enh: detached comments
rbernard
parents: 72
diff changeset
   348
        self.start_wrapper = self.end_wrapper = self.start_offset = self.end_offset = -1
61fd17f9ab78 enh: detached comments
rbernard
parents: 72
diff changeset
   349
        self.save()
61fd17f9ab78 enh: detached comments
rbernard
parents: 72
diff changeset
   350
        
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   351
# http://docs.djangoproject.com/en/dev/topics/files/#topics-files
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   352
511
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   353
# default conf values
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   354
DEFAULT_CONF = {
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   355
                'workspace_name' : 'Workspace',
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   356
                'site_url' : settings.SITE_URL,
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   357
                'email_from' : settings.DEFAULT_FROM_EMAIL,
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   358
                }
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   359
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   360
from cm.role_models import change_role_model
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   361
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   362
class ConfigurationManager(models.Manager):
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   363
    def set_workspace_name(self, workspace_name):
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   364
        if workspace_name:
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   365
            self.set_key('workspace_name', workspace_name)
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   366
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   367
    def get_key(self, key, default_value=None):
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   368
        try:
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   369
            return self.get(key=key).value
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   370
        except Configuration.DoesNotExist:
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   371
            return DEFAULT_CONF.get(key, default_value)
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   372
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   373
    def del_key(self, key):
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   374
        try:
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   375
            self.get(key=key).delete()
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   376
        except Configuration.DoesNotExist:
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   377
            return None
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   378
        
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   379
    def set_key(self, key, value):
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   380
        conf, created = self.get_or_create(key=key)
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   381
        if created or conf.value != value:
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   382
            conf.value = value
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   383
            conf.save()
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   384
            if key == 'workspace_role_model':
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   385
                change_role_model(value)
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   386
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   387
    def __getitem__(self, key):
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   388
        if not key.startswith('f_'):
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   389
            return self.get_key(key, None)
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   390
        else:
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   391
            return getattr(self,key)()
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   392
    
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   393
    def f_get_logo_url(self):
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   394
        key = self.get_key('workspace_logo_file_key', None)
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   395
        if key:
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   396
            attach = Attachment.objects.get(key=key)
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   397
            return attach.data.url
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   398
        else:
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   399
            return None 
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   400
    
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   401
import base64
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   402
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   403
class Configuration(models.Model):
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   404
    key = models.TextField(blank=False) # , unique=True cannot be added: creates error on mysql (?)
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   405
    raw_value = models.TextField(blank=False)
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   406
    
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   407
    def get_value(self):
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   408
        return pickle.loads(base64.b64decode(self.raw_value.encode('utf8')))
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   409
        
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   410
    def set_value(self, value):        
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   411
        self.raw_value = base64.b64encode(pickle.dumps(value, 0)).encode('utf8')
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   412
                
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   413
    value = property(get_value, set_value)
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   414
                
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   415
    objects = ConfigurationManager()
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   416
    
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   417
    def __unicode__(self):
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   418
        return '%s: %s' % (self.key, self.value)    
54d72b4da009 Reorder ConfigurationManager model, because it broke co-ment lite
Production Moz <dev@sopinspace.com>
parents: 504
diff changeset
   419
    
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   420
class AttachmentManager(KeyManager):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   421
    def create_attachment(self, text_version, filename, data):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   422
        attach = self.create(text_version=text_version)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   423
        ff = ContentFile(data)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   424
        attach.data.save(filename, ff)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   425
        return attach
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   426
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   427
class Attachment(KeyModel):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   428
    data = models.FileField(upload_to="attachments/%Y/%m/%d/", max_length=1000)
504
b2e0186daa5b Adds a category to comments, painted with colored vertical bar.
gibus
parents: 478
diff changeset
   429
    text_version = models.ForeignKey(TextVersion, null=True, blank=True, default=None)
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   430
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   431
    objects = AttachmentManager()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   432
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   433
class NotificationManager(KeyManager):
12
f69ff46d3240 various notification changes
reno
parents: 5
diff changeset
   434
    def create_notification(self, text, type, active, email_or_user):
f69ff46d3240 various notification changes
reno
parents: 5
diff changeset
   435
        notification = self.create(text=text, type=type, active=active)
f69ff46d3240 various notification changes
reno
parents: 5
diff changeset
   436
        notification.set_email_or_user(email_or_user)
f69ff46d3240 various notification changes
reno
parents: 5
diff changeset
   437
        return notification
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   438
12
f69ff46d3240 various notification changes
reno
parents: 5
diff changeset
   439
    def get_notifications(self, text, type, email_or_user):
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   440
        if isinstance(email_or_user,unicode):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   441
            prev_notifications = Notification.objects.filter(text=text, type=type, email=email_or_user)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   442
        else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   443
            prev_notifications = Notification.objects.filter(text=text, type=type, user=email_or_user)
12
f69ff46d3240 various notification changes
reno
parents: 5
diff changeset
   444
            
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   445
        if prev_notifications:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   446
            return prev_notifications[0]
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   447
        else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   448
            return None
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   449
     
12
f69ff46d3240 various notification changes
reno
parents: 5
diff changeset
   450
    def set_notification(self, text, type, active, email_or_user):
f69ff46d3240 various notification changes
reno
parents: 5
diff changeset
   451
        notification = self.get_notifications(text, type, email_or_user)
f69ff46d3240 various notification changes
reno
parents: 5
diff changeset
   452
        if notification == None :
f69ff46d3240 various notification changes
reno
parents: 5
diff changeset
   453
            self.create_notification(text, type, active, email_or_user)
f69ff46d3240 various notification changes
reno
parents: 5
diff changeset
   454
        else : 
f69ff46d3240 various notification changes
reno
parents: 5
diff changeset
   455
            notification.active = active
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   456
            notification.save()                
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   457
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   458
class Notification(KeyModel, AuthorModel):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   459
    text = models.ForeignKey(Text, null=True, blank=True)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   460
    type = models.CharField(max_length=30, null=True, blank=True)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   461
    active = models.BooleanField(default=True) # active = False means user desactivation
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   462
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   463
    objects = NotificationManager()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   464
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   465
    def desactivate_notification_url(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   466
        return reverse('desactivate-notification', args=[self.adminkey])
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   467
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   468
    def desactivate(self):    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   469
        if self.type=='own':
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   470
            self.active = False
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   471
            self.save()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   472
        else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   473
            self.delete()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   474
    
266
33eb2ee6b9de add notifications to admin area
raph
parents: 262
diff changeset
   475
    def __unicode__(self):
33eb2ee6b9de add notifications to admin area
raph
parents: 262
diff changeset
   476
        return u"%s: %s %s %s %s" % (self.__class__.__name__, self.user, self.text, self.type, self.active )
33eb2ee6b9de add notifications to admin area
raph
parents: 262
diff changeset
   477
    
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   478
# right management
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   479
class UserRoleManager(models.Manager):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   480
    def create_userroles_text(self, text):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   481
        # make sure every user has a userrole on this text
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   482
        for user in User.objects.all():
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   483
            userrole, _ = self.get_or_create(user=user, text=text)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   484
        # anon user
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   485
        userrole, _ = self.get_or_create(user=None, text=text)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   486
        # anon global user
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   487
        global_userrole, _ = self.get_or_create(user=None, text=None)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   488
            
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   489
class UserRole(models.Model):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   490
    role = models.ForeignKey("Role", null=True, blank=True)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   491
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   492
    # user == null => anyone
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   493
    user = models.ForeignKey(User, null=True, blank=True)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   494
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   495
    # text == null => any text (workspace role)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   496
    text = models.ForeignKey(Text, null=True, blank=True)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   497
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   498
    objects = UserRoleManager()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   499
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   500
    class Meta:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   501
        unique_together = (('role', 'user', 'text',))
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   502
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   503
    def __unicode__(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   504
        if self.role:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   505
            rolename = _(self.role.name)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   506
        else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   507
            rolename = ''
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   508
            
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   509
        if self.user:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   510
            return u"%s: %s %s %s" % (self.__class__.__name__, self.user.username, self.text, rolename)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   511
        else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   512
            return u"%s: *ALL* %s %s" % (self.__class__.__name__, self.text, rolename)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   513
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   514
    def __repr__(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   515
        return self.__unicode__()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   516
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   517
from cm.models_base import generate_key
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   518
from cm.utils.misc import update
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   519
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   520
class Role(models.Model):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   521
    """
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   522
    'Static' application roles 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   523
    """
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   524
    name = models.CharField(ugettext_lazy('name'), max_length=50, unique=True)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   525
    description = models.TextField(ugettext_lazy('description'))
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   526
    permissions = models.ManyToManyField(Permission, related_name="roles")
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   527
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   528
    global_scope = models.BooleanField('global scope', default=False) # applies to global scope only
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   529
    anon = models.BooleanField('anonymous', default=False) # role possible for anonymous users?
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   530
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   531
    def __unicode__(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   532
        return _(self.name)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   533
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   534
    def __hash__(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   535
        return self.id
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   536
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   537
    def name_i18n(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   538
        return _(self.name)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   539
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   540
from django.utils.safestring import mark_safe
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   541
 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   542
class RegistrationManager(KeyManager):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   543
    def activate_user(self, activation_key):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   544
        """
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   545
        Validates an activation key and activates the corresponding
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   546
        ``User`` if valid.
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   547
        If the key is valid , returns the ``User`` as second arg
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   548
        First is boolean indicating if user has just been activated
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   549
        """
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   550
        # Make sure the key we're trying conforms to the pattern of a
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   551
        # SHA1 hash; if it doesn't, no point trying to look it up in
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   552
        # the database.
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   553
        try:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   554
            profile = self.get(admin_key=activation_key)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   555
        except self.model.DoesNotExist:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   556
            return False, False
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   557
        user = profile.user
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   558
        activated = False
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   559
        if not user.is_active:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   560
            user.is_active = True
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   561
            user.save()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   562
            activated = True
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   563
        return (activated, user)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   564
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   565
    def _create_manager(self, email, username, password, first_name, last_name):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   566
        if username and email and password and len(User.objects.filter(username=username)) == 0:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   567
            user = User.objects.create(username=username, email=email, first_name=first_name, last_name=last_name, is_active=True)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   568
            user.set_password(password)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   569
            user.save()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   570
            
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   571
            profile = UserProfile.objects.create(user=user)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   572
                    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   573
            manager = Role.objects.get(name='Manager')
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   574
            UserRole.objects.create(text=None, user=user, role=manager)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   575
            return user
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   576
        else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   577
            return None
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   578
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   579
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   580
    def create_inactive_user(self, email, send_invitation, **kwargs):
448
054d572a3db4 Avoid warnings for deprecated instructions in djan 1.3
gibus
parents: 407
diff changeset
   581
        if 'postgresql' in settings.DATABASES['default']['ENGINE']:
305
df2c3202fd8e do not lock table with backends other than postgresql (postgresql specific syntax) (fixes #52)
raph
parents: 289
diff changeset
   582
            #prevent concurrent access 
df2c3202fd8e do not lock table with backends other than postgresql (postgresql specific syntax) (fixes #52)
raph
parents: 289
diff changeset
   583
            cursor = connection.cursor()
df2c3202fd8e do not lock table with backends other than postgresql (postgresql specific syntax) (fixes #52)
raph
parents: 289
diff changeset
   584
            sql = "LOCK TABLE auth_user IN EXCLUSIVE MODE"
df2c3202fd8e do not lock table with backends other than postgresql (postgresql specific syntax) (fixes #52)
raph
parents: 289
diff changeset
   585
            cursor.execute(sql)
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   586
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   587
        try:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   588
            user_with_email = User.objects.get(email__iexact=email)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   589
        except User.DoesNotExist:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   590
            user = User.objects.create(username=email, email=email)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   591
            profile = UserProfile.objects.create(user=user)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   592
            update(user, kwargs)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   593
            update(profile, kwargs)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   594
            
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   595
            user.is_active = False
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   596
            user.save()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   597
            profile.save()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   598
            
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   599
            note = kwargs.get('note', None) 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   600
            if send_invitation:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   601
                profile.send_activation_email(note)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   602
            return user
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   603
        else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   604
            return user_with_email
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   605
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   606
513
60da0b2cca9f Definitely this is not a good idea to use ApplicationConfiguration in TextVersion model as default for category_x fields.
Production Moz <dev@sopinspace.com>
parents: 512
diff changeset
   607
ApplicationConfiguration = Configuration.objects     
60da0b2cca9f Definitely this is not a good idea to use ApplicationConfiguration in TextVersion model as default for category_x fields.
Production Moz <dev@sopinspace.com>
parents: 512
diff changeset
   608
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   609
from cm.utils.mail import send_mail
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   610
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   611
class UserProfile(KeyModel):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   612
    modified = models.DateTimeField(auto_now=True)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   613
    created = models.DateTimeField(auto_now_add=True)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   614
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   615
    user = models.ForeignKey(User, unique=True)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   616
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   617
    allow_contact = models.BooleanField(ugettext_lazy(u'Allow contact'), default=True, help_text=ugettext_lazy(u"Allow email messages from other users"))    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   618
    preferred_language = models.CharField(ugettext_lazy(u'Preferred language'), max_length=2, default="en")
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   619
    is_temp = models.BooleanField(default=False)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   620
    is_email_error = models.BooleanField(default=False)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   621
    is_suspended = models.BooleanField(ugettext_lazy(u'Suspended access'), default=False) # used to disable access or to wait for approval when registering
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   622
38
be1807d390d4 - add tag support to user
raph
parents: 24
diff changeset
   623
    tags = TagField(ugettext_lazy("Tags"), max_length=1000)
be1807d390d4 - add tag support to user
raph
parents: 24
diff changeset
   624
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   625
    objects = RegistrationManager()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   626
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   627
    class Meta:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   628
        permissions = (
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   629
            ("can_create_user", "Can create user"),
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   630
            ("can_delete_user", "Can delete user"),
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   631
        )
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   632
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   633
    def __unicode__(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   634
        return unicode(self.user)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   635
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   636
    def global_userrole(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   637
        try:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   638
            return UserRole.objects.get(user=self.user, text=None)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   639
        except UserRole.DoesNotExist:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   640
            return None
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   641
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   642
    def admin_print(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   643
        if self.is_suspended:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   644
            if self.user.is_active:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   645
                return mark_safe('%s (%s)' % (self.user.username, _(u'suspended'),))
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   646
            else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   647
                return mark_safe('%s (%s)' % (self.user.username, _(u'waiting approval'),))
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   648
        else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   649
            if self.user.is_active:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   650
                return mark_safe('%s' % self.user.username) 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   651
            else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   652
                email_username = self.user.email.split('@')[0]
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   653
                return mark_safe('%s (%s)' % (self.user.username, _(u'pending'),))
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   654
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   655
    def simple_print(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   656
        if self.user.is_active:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   657
            return self.user.username 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   658
        else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   659
            return self.user.email
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   660
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   661
    def send_activation_email(self, note=None):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   662
        self._send_act_invit_email(note=note, template='email/activation_email.txt')
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   663
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   664
    def send_invitation_email(self, note=None):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   665
        self._send_act_invit_email(note=note, template='email/invitation_email.txt')
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   666
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   667
    def _send_act_invit_email(self, template, note=None):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   668
        subject = _(u'Invitation')
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   669
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   670
        activate_url = reverse('user-activate', args=[self.adminkey])
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   671
        message = render_to_string(template,
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   672
                                   { 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   673
                                     'activate_url' : activate_url,
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   674
                                     'note' : note,
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   675
                                     'CONF': ApplicationConfiguration
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   676
                                      })
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   677
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   678
        send_mail(subject, message, ApplicationConfiguration['email_from'], [self.user.email])
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   679
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   680
from django.db.models import signals
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   681
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   682
def delete_profile(sender, **kwargs):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   683
    user_profile = kwargs['instance']
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   684
    user = user_profile.user
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   685
    user.delete()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   686
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   687
signals.post_delete.connect(delete_profile, sender=UserProfile)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   688
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   689
class ActivityManager(models.Manager):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   690
    pass
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   691
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   692
class Activity(models.Model):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   693
    created = models.DateTimeField(auto_now_add=True)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   694
    originator_user = models.ForeignKey(User, related_name='originator_activity', null=True, blank=True, default=None)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   695
    text = models.ForeignKey(Text, null=True, blank=True, default=None)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   696
    text_version = models.ForeignKey(TextVersion, null=True, blank=True, default=None)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   697
    comment = models.ForeignKey(Comment, null=True, blank=True, default=None)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   698
    user = models.ForeignKey(User, null=True, blank=True, default=None)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   699
    type = models.CharField(max_length=30)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   700
    ip = models.IPAddressField(null=True, blank=True, default=None)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   701
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   702
    objects = ActivityManager()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   703
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   704
    # viewable activities (i.e. now 'text-view')
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   705
    VIEWABLE_ACTIVITIES = {
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   706
                   'view_comments' : ['comment_created', 'comment_removed'],
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   707
                   'view_users' : ['user_created', 'user_activated', 'user_refused', 'user_enabled', 'user_approved', 'user_suspended'],
460
2fdb7d095d5c Added import from XML file, including text, comments and attachments.
gibus
parents: 448
diff changeset
   708
                   'view_texts' : ['text_created', 'text_imported', 'text_removed', 'text_edited', 'text_edited_new_version'],
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   709
                   }
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   710
    ACTIVITIES_TYPES = reduce(list.__add__, VIEWABLE_ACTIVITIES.values())
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   711
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   712
    IMGS = {
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   713
            'text_created' : u'page_add_small.png',
460
2fdb7d095d5c Added import from XML file, including text, comments and attachments.
gibus
parents: 448
diff changeset
   714
            'text_imported' : u'sop_import_small.png',
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   715
            'text_removed' : u'page_delete_small.png',
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   716
            'text_edited'  : u'page_save_small.png',
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   717
            'text_edited_new_version' : u'page_save_small.png',
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   718
            'user_created' : u'user_add_small.png',
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   719
            'user_enabled' : u'user_add_small.png',
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   720
            'user_refused': u'user_delete_small.png',
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   721
            'user_suspended': u'user_delete_small.png',
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   722
            'user_approved': u'user_add_small.png',
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   723
            'user_activated' : u'user_go.png',
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   724
            'comment_created' : u'note_add_small.png',
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   725
            'comment_removed' : u'note_delete_small.png',
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   726
        }
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   727
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   728
    #type/msg
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   729
    MSGS = {
227
57492cd7e162 add author in activities traces
raph
parents: 175
diff changeset
   730
         'text_edited' : ugettext_lazy(u'Text %(link_to_text)s edited by %(creator)s'),
57492cd7e162 add author in activities traces
raph
parents: 175
diff changeset
   731
         'text_edited_new_version' : ugettext_lazy(u'Text %(link_to_text)s edited (new version created) by %(creator)s'),
57492cd7e162 add author in activities traces
raph
parents: 175
diff changeset
   732
         'text_created' :  ugettext_lazy(u'Text %(link_to_text)s added by %(creator)s'),
460
2fdb7d095d5c Added import from XML file, including text, comments and attachments.
gibus
parents: 448
diff changeset
   733
         'text_imported' :  ugettext_lazy(u'Text %(link_to_text)s imported by %(creator)s'),
5
c3594e4df7c1 lazy strings
raph
parents: 0
diff changeset
   734
         'text_removed' : ugettext_lazy(u'Text %(link_to_text)s removed'),
227
57492cd7e162 add author in activities traces
raph
parents: 175
diff changeset
   735
         'comment_created' : ugettext_lazy(u'Comment %(link_to_comment)s added on text %(link_to_text)s by %(creator)s'),
5
c3594e4df7c1 lazy strings
raph
parents: 0
diff changeset
   736
         'comment_removed' : ugettext_lazy(u'Comment %(link_to_comment)s removed from text %(link_to_text)s'),
c3594e4df7c1 lazy strings
raph
parents: 0
diff changeset
   737
         'user_created' : ugettext_lazy(u'User %(username)s added'),
c3594e4df7c1 lazy strings
raph
parents: 0
diff changeset
   738
         'user_enabled' : ugettext_lazy(u'User %(username)s access to workspace enabled'),
c3594e4df7c1 lazy strings
raph
parents: 0
diff changeset
   739
         'user_refused' : ugettext_lazy(u'User %(username)s access to workspace refused'),
c3594e4df7c1 lazy strings
raph
parents: 0
diff changeset
   740
         'user_suspended' : ugettext_lazy(u'User %(username)s access to workspace suspended'),
c3594e4df7c1 lazy strings
raph
parents: 0
diff changeset
   741
         'user_activated' : ugettext_lazy(u'User %(username)s access to workspace activated'),
c3594e4df7c1 lazy strings
raph
parents: 0
diff changeset
   742
         'user_approved' : ugettext_lazy(u'User %(username)s has activated his account'),
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   743
         }
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   744
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   745
    def is_same_user(self, other_activity):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   746
        if (self.originator_user != None or other_activity.originator_user != None) and self.originator_user != other_activity.originator_user:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   747
            return False
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   748
        else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   749
            return self.ip != None and self.ip == other_activity.ip
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   750
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   751
    def linkable_text_title(self, html=True, link=True):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   752
        # html: whether or not output sould be html
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   753
        format_args = {'link':absolute_reverse('text-view', args=[self.text.key]), 'title':self.text.title}
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   754
        if html and not self.text.deleted :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   755
            return mark_safe(u'<a href="%(link)s">%(title)s</a>' % format_args)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   756
        else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   757
            if link and not self.text.deleted:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   758
                return u'%(title)s (%(link)s)' % format_args
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   759
            else:             
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   760
                return self.text.title ;
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   761
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   762
    def linkable_comment_title(self, html=True, link=True):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   763
        if self.comment:
144
e7e1bc64f613 lpermalink uses id_key
rbernard
parents: 140
diff changeset
   764
            format_args = {'link':absolute_reverse('text-view-show-comment', args=[self.text.key, self.comment.id_key]), 'title':self.comment.title}
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   765
            if html and not self.comment.deleted and not self.text.deleted:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   766
                return mark_safe(u'<a href="%(link)s">%(title)s</a>' % format_args)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   767
            else :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   768
                if link and not self.comment.deleted and not self.text.deleted:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   769
                    return u'%(title)s (%(link)s)' % format_args
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   770
                else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   771
                    return self.comment.title ;
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   772
        else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   773
            return u''
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   774
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   775
    def __unicode__(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   776
        return u"%s %s %s %s %s" % (self.type, self.originator_user, self.text, self.comment, self.user)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   777
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   778
    def img_name(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   779
        return self.IMGS.get(self.type)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   780
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   781
    def printable_data_nohtml_link(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   782
        return self.printable_data(html=False, link=True)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   783
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   784
    def printable_data(self, html=True, link=True):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   785
        msg = self.MSGS.get(self.type, None)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   786
        if msg:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   787
            return mark_safe(msg % {
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   788
                                     'link_to_text' : self.linkable_text_title(html=html, link=link) if self.text else None,
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   789
                                     'link_to_comment' : self.linkable_comment_title(html=html, link=link) if self.comment else None,
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   790
                                     'username' : self.user.username if self.user else None,
227
57492cd7e162 add author in activities traces
raph
parents: 175
diff changeset
   791
                                     'creator' : self.originator_user.username if self.originator_user else ugettext_lazy(u'anonymous'),
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   792
                                    })
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   793
        return ''
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   794
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   795
    def printable_metadata(self, html=True):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   796
        ret = []
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   797
        if self.type == 'user_activated':
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   798
            ret.append(_(u'by "%(username)s"') % {'username' : self.originator_user.username})
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   799
            ret.append(' ')
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   800
        ret.append(_(u"%(time_since)s ago") % {'time_since':timesince(self.created)})
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   801
        return ''.join(ret)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   802
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   803
    def printable_metadata_absolute(self, html=True):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   804
        ret = []
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   805
        if self.type == 'user_activated':
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   806
            ret.append(_(u'by "%(username)s"') % {'username' : self.originator_user.username})
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   807
            ret.append(u' ')
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   808
        ret.append(datetime_to_user_str(self.created))
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   809
        return u''.join(ret)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   810
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   811
import cm.denorm_engine
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   812
import cm.admin
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   813
import cm.main
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   814
import cm.activity
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   815
import cm.notifications
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   816
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   817
# we fill username with email so we need a bigger value 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   818
User._meta.get_field('username').max_length = 75
347
0a359382701b prevent uno custom __import__ from messing with south import machinery (to discover south enabled dj apps)
Production Moz <dev@sopinspace.com>
parents: 327
diff changeset
   819
0a359382701b prevent uno custom __import__ from messing with south import machinery (to discover south enabled dj apps)
Production Moz <dev@sopinspace.com>
parents: 327
diff changeset
   820
import monkey_patches