src/cm/models.py
author Simon Descarpentries <sid@sopinspace.com>
Mon, 21 Oct 2013 16:37:07 +0200
changeset 553 bf26fb47a14c
parent 518 9172f4c6ad70
child 605 830993bdf983
permissions -rw-r--r--
To allow scrolling in Safari mobile, we set the content of text_view_comments frame in a jQuery UI layout. So the automated scrolling operations in c_sync.js must be adjustable to the right part to scroll. Also, if a comment have to be shown outside of the current viewport, we scroll the correct part to that viewport and then set the comment top Y offset to juste what it needs to avoid the "Add comment" button after scrolling operation. If not in Safari mobile, we add an offset here to avoid comment to display under the "Add comment" button.
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
518
9172f4c6ad70 Better translation of help text
gibus
parents: 515
diff changeset
   197
    category_1 = models.CharField(ugettext_lazy("Label for the first category of comments"), max_length=20, null=True, blank=True)
9172f4c6ad70 Better translation of help text
gibus
parents: 515
diff changeset
   198
    category_2 = models.CharField(ugettext_lazy("Label for the second category of comments"), max_length=20, null=True, blank=True)
9172f4c6ad70 Better translation of help text
gibus
parents: 515
diff changeset
   199
    category_3 = models.CharField(ugettext_lazy("Label for the third category of comments"), max_length=20, null=True, blank=True)
9172f4c6ad70 Better translation of help text
gibus
parents: 515
diff changeset
   200
    category_4 = models.CharField(ugettext_lazy("Label for the fourth category of comments"), max_length=20, null=True, blank=True)
9172f4c6ad70 Better translation of help text
gibus
parents: 515
diff changeset
   201
    category_5 = models.CharField(ugettext_lazy("Label for the fifth category of comments"), max_length=20, null=True, blank=True)
514
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
    
515
0be906e586e6 Fix south migration problem caused by 0003_update_keys_to_textversion using TextVersion model which is updated only in 0010_auto__add_field_textversion_category_1__add_field_textversion_category, same with 0007_populate_id_key_in_comments using Comment model updated in 0011_auto__add_field_comment_category.
Production Moz <dev@sopinspace.com>
parents: 514
diff changeset
   420
ApplicationConfiguration = Configuration.objects     
0be906e586e6 Fix south migration problem caused by 0003_update_keys_to_textversion using TextVersion model which is updated only in 0010_auto__add_field_textversion_category_1__add_field_textversion_category, same with 0007_populate_id_key_in_comments using Comment model updated in 0011_auto__add_field_comment_category.
Production Moz <dev@sopinspace.com>
parents: 514
diff changeset
   421
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   422
class AttachmentManager(KeyManager):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   423
    def create_attachment(self, text_version, filename, data):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   424
        attach = self.create(text_version=text_version)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   425
        ff = ContentFile(data)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   426
        attach.data.save(filename, ff)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   427
        return attach
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   428
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   429
class Attachment(KeyModel):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   430
    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
   431
    text_version = models.ForeignKey(TextVersion, null=True, blank=True, default=None)
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   432
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   433
    objects = AttachmentManager()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   434
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   435
class NotificationManager(KeyManager):
12
f69ff46d3240 various notification changes
reno
parents: 5
diff changeset
   436
    def create_notification(self, text, type, active, email_or_user):
f69ff46d3240 various notification changes
reno
parents: 5
diff changeset
   437
        notification = self.create(text=text, type=type, active=active)
f69ff46d3240 various notification changes
reno
parents: 5
diff changeset
   438
        notification.set_email_or_user(email_or_user)
f69ff46d3240 various notification changes
reno
parents: 5
diff changeset
   439
        return notification
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   440
12
f69ff46d3240 various notification changes
reno
parents: 5
diff changeset
   441
    def get_notifications(self, text, type, email_or_user):
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   442
        if isinstance(email_or_user,unicode):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   443
            prev_notifications = Notification.objects.filter(text=text, type=type, email=email_or_user)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   444
        else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   445
            prev_notifications = Notification.objects.filter(text=text, type=type, user=email_or_user)
12
f69ff46d3240 various notification changes
reno
parents: 5
diff changeset
   446
            
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   447
        if prev_notifications:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   448
            return prev_notifications[0]
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   449
        else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   450
            return None
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   451
     
12
f69ff46d3240 various notification changes
reno
parents: 5
diff changeset
   452
    def set_notification(self, text, type, active, email_or_user):
f69ff46d3240 various notification changes
reno
parents: 5
diff changeset
   453
        notification = self.get_notifications(text, type, email_or_user)
f69ff46d3240 various notification changes
reno
parents: 5
diff changeset
   454
        if notification == None :
f69ff46d3240 various notification changes
reno
parents: 5
diff changeset
   455
            self.create_notification(text, type, active, email_or_user)
f69ff46d3240 various notification changes
reno
parents: 5
diff changeset
   456
        else : 
f69ff46d3240 various notification changes
reno
parents: 5
diff changeset
   457
            notification.active = active
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   458
            notification.save()                
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   459
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   460
class Notification(KeyModel, AuthorModel):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   461
    text = models.ForeignKey(Text, null=True, blank=True)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   462
    type = models.CharField(max_length=30, null=True, blank=True)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   463
    active = models.BooleanField(default=True) # active = False means user desactivation
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   464
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   465
    objects = NotificationManager()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   466
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   467
    def desactivate_notification_url(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   468
        return reverse('desactivate-notification', args=[self.adminkey])
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   469
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   470
    def desactivate(self):    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   471
        if self.type=='own':
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   472
            self.active = False
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   473
            self.save()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   474
        else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   475
            self.delete()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   476
    
266
33eb2ee6b9de add notifications to admin area
raph
parents: 262
diff changeset
   477
    def __unicode__(self):
33eb2ee6b9de add notifications to admin area
raph
parents: 262
diff changeset
   478
        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
   479
    
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   480
# right management
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   481
class UserRoleManager(models.Manager):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   482
    def create_userroles_text(self, text):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   483
        # make sure every user has a userrole on this text
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   484
        for user in User.objects.all():
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   485
            userrole, _ = self.get_or_create(user=user, text=text)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   486
        # anon user
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   487
        userrole, _ = self.get_or_create(user=None, text=text)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   488
        # anon global user
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   489
        global_userrole, _ = self.get_or_create(user=None, text=None)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   490
            
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   491
class UserRole(models.Model):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   492
    role = models.ForeignKey("Role", null=True, blank=True)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   493
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   494
    # user == null => anyone
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   495
    user = models.ForeignKey(User, null=True, blank=True)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   496
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   497
    # text == null => any text (workspace role)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   498
    text = models.ForeignKey(Text, null=True, blank=True)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   499
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   500
    objects = UserRoleManager()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   501
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   502
    class Meta:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   503
        unique_together = (('role', 'user', 'text',))
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   504
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   505
    def __unicode__(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   506
        if self.role:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   507
            rolename = _(self.role.name)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   508
        else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   509
            rolename = ''
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   510
            
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   511
        if self.user:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   512
            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
   513
        else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   514
            return u"%s: *ALL* %s %s" % (self.__class__.__name__, self.text, rolename)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   515
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   516
    def __repr__(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   517
        return self.__unicode__()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   518
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   519
from cm.models_base import generate_key
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   520
from cm.utils.misc import update
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   521
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   522
class Role(models.Model):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   523
    """
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   524
    'Static' application roles 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   525
    """
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   526
    name = models.CharField(ugettext_lazy('name'), max_length=50, unique=True)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   527
    description = models.TextField(ugettext_lazy('description'))
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   528
    permissions = models.ManyToManyField(Permission, related_name="roles")
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   529
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   530
    global_scope = models.BooleanField('global scope', default=False) # applies to global scope only
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   531
    anon = models.BooleanField('anonymous', default=False) # role possible for anonymous users?
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   532
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   533
    def __unicode__(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   534
        return _(self.name)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   535
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   536
    def __hash__(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   537
        return self.id
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   538
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   539
    def name_i18n(self):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   540
        return _(self.name)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   541
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   542
from django.utils.safestring import mark_safe
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   543
 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   544
class RegistrationManager(KeyManager):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   545
    def activate_user(self, activation_key):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   546
        """
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   547
        Validates an activation key and activates the corresponding
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   548
        ``User`` if valid.
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   549
        If the key is valid , returns the ``User`` as second arg
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   550
        First is boolean indicating if user has just been activated
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   551
        """
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   552
        # Make sure the key we're trying conforms to the pattern of a
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   553
        # 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
   554
        # the database.
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   555
        try:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   556
            profile = self.get(admin_key=activation_key)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   557
        except self.model.DoesNotExist:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   558
            return False, False
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   559
        user = profile.user
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   560
        activated = False
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   561
        if not user.is_active:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   562
            user.is_active = True
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   563
            user.save()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   564
            activated = True
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   565
        return (activated, user)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   566
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   567
    def _create_manager(self, email, username, password, first_name, last_name):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   568
        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
   569
            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
   570
            user.set_password(password)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   571
            user.save()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   572
            
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   573
            profile = UserProfile.objects.create(user=user)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   574
                    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   575
            manager = Role.objects.get(name='Manager')
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   576
            UserRole.objects.create(text=None, user=user, role=manager)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   577
            return user
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   578
        else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   579
            return None
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   580
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   581
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   582
    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
   583
        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
   584
            #prevent concurrent access 
df2c3202fd8e do not lock table with backends other than postgresql (postgresql specific syntax) (fixes #52)
raph
parents: 289
diff changeset
   585
            cursor = connection.cursor()
df2c3202fd8e do not lock table with backends other than postgresql (postgresql specific syntax) (fixes #52)
raph
parents: 289
diff changeset
   586
            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
   587
            cursor.execute(sql)
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   588
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   589
        try:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   590
            user_with_email = User.objects.get(email__iexact=email)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   591
        except User.DoesNotExist:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   592
            user = User.objects.create(username=email, email=email)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   593
            profile = UserProfile.objects.create(user=user)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   594
            update(user, kwargs)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   595
            update(profile, kwargs)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   596
            
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   597
            user.is_active = False
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   598
            user.save()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   599
            profile.save()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   600
            
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   601
            note = kwargs.get('note', None) 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   602
            if send_invitation:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   603
                profile.send_activation_email(note)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   604
            return user
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   605
        else:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   606
            return user_with_email
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   607
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   608
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