src/cm/client.py
author rbernard
Wed, 20 Jan 2010 22:32:59 +0100
changeset 106 36165e7cd1f0
parent 24 c8a95e540b79
child 144 e7e1bc64f613
permissions -rw-r--r--
i18n typo
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
     1
from django.forms.fields import email_re
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
     2
from django.http import HttpResponse, HttpResponseRedirect
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
     3
from django.core.exceptions import ObjectDoesNotExist
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
     4
from django.forms import ValidationError
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
     5
from django.utils import simplejson
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
     6
from django.utils.translation import ugettext as _
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
     7
from tagging.models import Tag
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
     8
from tagging.utils import parse_tag_input, LOGARITHMIC, calculate_cloud
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
     9
from tagging.models import TaggedItem
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    10
from cm.models import *
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    11
from cm.utils.timezone import request_tz_convert
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    12
from itertools import groupby
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    13
from time import mktime, sleep
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    14
from cm.converters.pandoc_converters import pandoc_convert
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    15
from cm.security import get_viewable_comments, list_viewable_comments, has_perm, has_perm_on_text, has_perm_on_comment, has_own_perm
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    16
from cm.activity import register_activity
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    17
from cm.utils.date import datetime_to_user_str, datetime_to_epoch
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    18
from cm.cm_settings import AUTO_CONTRIB_REGISTER
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    19
from settings import CLIENT_DATE_FMT
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    20
import re
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    21
import time
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    22
import operator
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    23
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    24
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    25
selection_place_error_msg = _(u'A selection is required. Select in the text the part your comment applies to.')
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    26
comment_states = ('approved', 'unapproved', 'pending')
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    27
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    28
def is_valid_email(email):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    29
    if email_re.match(email) : 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    30
        return True 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    31
    return False
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    32
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    33
#
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    34
def jsonize(obj, request):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    35
    return simplejson.dumps(obj, cls=RequestComplexEncoder, request=request)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    36
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    37
class RequestComplexEncoder(simplejson.JSONEncoder):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    38
    def __init__(self, request, **kw):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    39
        self.request = request
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    40
        simplejson.JSONEncoder.__init__(self, **kw)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    41
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    42
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    43
    def default(self, obj):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    44
        if isinstance(obj, Comment) :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    45
            comment = obj
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    46
            #replies = list(comment.comment_set.order_by('created'))
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    47
            text=comment.text_version.text
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    48
            replies = get_viewable_comments(self.request, comment.comment_set.all(), text)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    49
            
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    50
            # can_view == true because of get_viewable_comments filter
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    51
            can_moderate = has_perm(self.request, 'can_edit_comment', text)   
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    52
            can_edit = has_perm(self.request, 'can_edit_comment', text) or has_own_perm(self.request, 'can_edit_comment_own', text, comment)  
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    53
            can_delete = has_perm(self.request, 'can_delete_comment', text) or has_own_perm(self.request, 'can_delete_comment_own', text, comment)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    54
            
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    55
            return {'id' : comment.id, 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    56
                    'key' : comment.key,
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    57
                   'created_user_str' : datetime_to_user_str(request_tz_convert(comment.created, self.request)),
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    58
                   'modified_user_str' : datetime_to_user_str(request_tz_convert(comment.modified, self.request)),
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    59
#                   'created_str' : datetime_to_str(comment.created), # TODO change to a simple number as modified if possible
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    60
                   'created' : datetime_to_epoch(comment.created), # TODO change to a simple number as modified if possible
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    61
                   'modified' : datetime_to_epoch(comment.modified),  
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    62
#                   'modified' : time.mktime(comment.modified.timetuple()),  
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    63
#                   'created' : datetime_to_js_date_str(comment.created),
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    64
                   'reply_to_id' : comment.reply_to_id,
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    65
                   'replies' : replies,
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    66
                   'name' : comment.get_name(), 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    67
                   'email' : comment.get_email(), 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    68
                   'logged_author' : (comment.user != None), 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    69
                   'title':comment.title,
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    70
                   'content':comment.content, 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    71
                   'content_html':comment.content_html, 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    72
                   'tags': ', '.join(parse_tag_input(comment.tags)), 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    73
                   'format': comment.format, 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    74
                   'start_wrapper' : comment.start_wrapper, 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    75
                   'end_wrapper' : comment.end_wrapper,
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    76
                   'start_offset' : comment.start_offset, 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    77
                   'end_offset' : comment.end_offset,
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    78
                   'state' : comment.state,
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    79
                   'permalink' : reverse('text-view-show-comment', args=[text.key, comment.key]),
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    80
                   # permission
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    81
                   'can_edit' : can_edit,
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    82
                   'can_delete' : can_delete,
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    83
                   'can_moderate' : can_moderate,
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    84
                   }
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    85
        if isinstance(obj, Tag) :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    86
            tag = obj
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    87
            # RBE each time issuing a db request to find comments related to this tag !!! TODO  
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    88
            return { 'ids' : [t.id for t in tag.items.all()], 'name' : tag.name, 'font_size' : tag.font_size}            
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    89
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    90
        return simplejson.JSONEncoder.default(self, obj)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    91
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    92
def experiment() :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    93
    sleep(5) ;
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    94
    return {"key":"value"}
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    95
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    96
def read_comment_args(request):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    97
    name = request.POST.get('name', None)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    98
    email = request.POST.get('email', None)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
    99
    if name != None :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   100
        name = name.lower().strip()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   101
    if email != None :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   102
        email = email.lower().strip()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   103
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   104
    title = request.POST['title'].strip()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   105
    content = request.POST['content'].strip() 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   106
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   107
    tags = request.POST['tags']
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   108
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   109
    reply_to_id = request.POST.get('reply_to_id', None)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   110
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   111
    format = request.POST['format'] 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   112
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   113
    start_wrapper = request.POST.get('start_wrapper', None)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   114
    end_wrapper = request.POST.get('end_wrapper', None)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   115
    start_offset = request.POST.get('start_offset', None)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   116
    end_offset = request.POST.get('end_offset', None)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   117
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   118
    if start_wrapper :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   119
        start_wrapper = int(start_wrapper.strip())
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   120
    if end_wrapper :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   121
        end_wrapper = int(end_wrapper.strip())
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   122
    if start_offset :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   123
        start_offset = int(start_offset.strip())
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   124
    if end_offset :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   125
        end_offset = int(end_offset.strip())
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   126
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   127
    return name, email, title, content, tags, reply_to_id, format, start_wrapper, end_wrapper, start_offset, end_offset
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   128
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   129
def validate_comment_args(name, email, title, content, tags):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   130
    errors = {}
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   131
    if name != None : 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   132
        if name == "" :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   133
            errors['name'] = _(u'name is required')   
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   134
    if email != None :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   135
        if email == "" :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   136
            errors['email'] = _(u'email is required')
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   137
        if not is_valid_email(email) :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   138
            errors['email'] = _('invalid email')
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   139
    if title == "" :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   140
        errors['title'] = _(u'title is required')   
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   141
    if content == "" :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   142
        errors['content'] = _(u'content is required')
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   143
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   144
    tag_errors = validate_tags(tags)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   145
    if tag_errors != "" :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   146
        errors['tags'] = tag_errors
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   147
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   148
    return errors
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   149
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   150
@has_perm_on_comment("can_delete_comment")
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   151
def remove_comment(request, key, comment_key):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   152
    ret={}
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   153
    try:
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   154
        text = Text.objects.get(key=key)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   155
        comment = Comment.objects.get(key = comment_key)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   156
        comment.delete()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   157
        ret['msg'] = _(u'comment removed')
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   158
        register_activity(request, "comment_removed", text=text, comment=comment)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   159
    except ObjectDoesNotExist: 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   160
        pass
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   161
    return ret ;
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   162
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   163
@has_perm_on_comment("can_edit_comment")
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   164
def edit_comment(request, key, comment_key):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   165
    state = request.POST.get('state', None)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   166
    change_state = state and state in comment_states     
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   167
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   168
    errors = {}
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   169
    if not change_state : # moderation action
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   170
        change_scope = request.POST.get('change_scope', None)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   171
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   172
        name, email, title, content, tags, reply_to_id, format, start_wrapper, end_wrapper, start_offset, end_offset = read_comment_args(request)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   173
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   174
        errors = validate_comment_args(name, email, title, content, tags)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   175
         
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   176
        if (change_scope) and start_wrapper=="" :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   177
            errors['selection_place'] = selection_place_error_msg   
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   178
            
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   179
        content_html = pandoc_convert(content, format, "html", full=False)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   180
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   181
    ret = {} 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   182
    if errors != {} :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   183
        ret['errors'] = errors
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   184
    else :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   185
    # INSERT
106
rbernard
parents: 24
diff changeset
   186
    # TODO check version is latest (if boolean
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   187
        #comment = Comment.objects.get(id=edit_comment_id)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   188
        comment = Comment.objects.get(key=comment_key)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   189
        if change_state : # moderation action
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   190
            comment.state = state 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   191
        else :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   192
            comment.name = name
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   193
            comment.email = email
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   194
            comment.title = title
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   195
            comment.content = content
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   196
            comment.content_html = content_html
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   197
            comment.tags = tags
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   198
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   199
            if change_scope :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   200
                comment.start_wrapper = start_wrapper
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   201
                comment.start_offset = start_offset
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   202
                comment.end_wrapper = end_wrapper
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   203
                comment.end_offset = end_offset
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   204
            
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   205
        comment.save()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   206
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   207
        ret['comment'] = comment
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   208
        ret['msg'] = _(u'comment saved')
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   209
    return ret
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   210
    
12
f69ff46d3240 various notification changes
reno
parents: 0
diff changeset
   211
# DIRTY : this function has no error check but anyway errors are not listened to client side 
f69ff46d3240 various notification changes
reno
parents: 0
diff changeset
   212
@has_perm_on_text("can_create_comment")
f69ff46d3240 various notification changes
reno
parents: 0
diff changeset
   213
def own_notify(request, key):
f69ff46d3240 various notification changes
reno
parents: 0
diff changeset
   214
    email_or_user = None if request.user.is_anonymous() else request.user
f69ff46d3240 various notification changes
reno
parents: 0
diff changeset
   215
    if not email_or_user :
f69ff46d3240 various notification changes
reno
parents: 0
diff changeset
   216
        email_or_user = request.POST.get('email', None)
f69ff46d3240 various notification changes
reno
parents: 0
diff changeset
   217
        if email_or_user :
f69ff46d3240 various notification changes
reno
parents: 0
diff changeset
   218
            email_or_user = email_or_user.lower().strip()
f69ff46d3240 various notification changes
reno
parents: 0
diff changeset
   219
17
a4be0b8a905d bug fix : can view own comment on comment add on mod priori
reno
parents: 12
diff changeset
   220
    active = (request.POST.get('active', False) == 'true')
12
f69ff46d3240 various notification changes
reno
parents: 0
diff changeset
   221
    text = Text.objects.get(key=key)
17
a4be0b8a905d bug fix : can view own comment on comment add on mod priori
reno
parents: 12
diff changeset
   222
    Notification.objects.set_notification(text=None, type='own', active=active, email_or_user=email_or_user)
12
f69ff46d3240 various notification changes
reno
parents: 0
diff changeset
   223
    ret = HttpResponse()
f69ff46d3240 various notification changes
reno
parents: 0
diff changeset
   224
    ret.status_code = 200 
f69ff46d3240 various notification changes
reno
parents: 0
diff changeset
   225
    return ret 
f69ff46d3240 various notification changes
reno
parents: 0
diff changeset
   226
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   227
@has_perm_on_text("can_create_comment")
24
c8a95e540b79 ENH : adding comments on previous version now possible
reno
parents: 17
diff changeset
   228
def add_comment(request, key, version_key):
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   229
#    if edit_comment_id : #
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   230
#    if self.request.user.is_anonymous() : # accessing via an admin url ?
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   231
#    and comment.user == self.request.user
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   232
    user = None if request.user.is_anonymous() else request.user 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   233
    name, email, title, content, tags, reply_to_id, format, start_wrapper, end_wrapper, start_offset, end_offset = read_comment_args(request)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   234
    errors = {} 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   235
    errors = validate_comment_args(name, email, title, content, tags)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   236
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   237
    if start_wrapper == "" :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   238
        errors['selection_place'] = selection_place_error_msg   
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   239
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   240
    #TODO validate pandoc conversion
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   241
    content_html = pandoc_convert(content, format, "html", full=False)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   242
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   243
    ret = {} 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   244
    if errors != {} :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   245
        ret['errors'] = errors
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   246
    else :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   247
    # INSERT
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   248
    # TODO check version still exist ...
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   249
        reply_to = None
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   250
        if reply_to_id :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   251
            reply_to = Comment.objects.get(id=reply_to_id)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   252
            
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   253
        text = Text.objects.get(key=key)
24
c8a95e540b79 ENH : adding comments on previous version now possible
reno
parents: 17
diff changeset
   254
        text_version = TextVersion.objects.get(key=version_key)
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   255
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   256
        comment_state = 'approved' if text_version.mod_posteriori else 'pending'
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   257
        comment = Comment.objects.create(state=comment_state, text_version=text_version, user=user, name=name, email=email, title=title, content=content, content_html=content_html, tags = tags, start_wrapper = start_wrapper, end_wrapper = end_wrapper, start_offset = start_offset, end_offset = end_offset, reply_to=reply_to)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   258
        
12
f69ff46d3240 various notification changes
reno
parents: 0
diff changeset
   259
        ask_for_notification = True
f69ff46d3240 various notification changes
reno
parents: 0
diff changeset
   260
        if user : 
f69ff46d3240 various notification changes
reno
parents: 0
diff changeset
   261
            workspace_notify_count = Notification.objects.filter(text=None,type='workspace',user=user, active=True).count()
f69ff46d3240 various notification changes
reno
parents: 0
diff changeset
   262
            text_notify_count = Notification.objects.filter(text=text,type='text',user=user, active=True).count()
f69ff46d3240 various notification changes
reno
parents: 0
diff changeset
   263
            if workspace_notify_count > 0 or text_notify_count > 0 : 
f69ff46d3240 various notification changes
reno
parents: 0
diff changeset
   264
                ask_for_notification = False
f69ff46d3240 various notification changes
reno
parents: 0
diff changeset
   265
f69ff46d3240 various notification changes
reno
parents: 0
diff changeset
   266
        if ask_for_notification :
f69ff46d3240 various notification changes
reno
parents: 0
diff changeset
   267
            ask_for_notification = ( None == Notification.objects.get_notifications(text=None, type='own', email_or_user=(user if user else email)))
f69ff46d3240 various notification changes
reno
parents: 0
diff changeset
   268
        ret['ask_for_notification'] = ask_for_notification
f69ff46d3240 various notification changes
reno
parents: 0
diff changeset
   269
        ret['email'] = '' if user else email
17
a4be0b8a905d bug fix : can view own comment on comment add on mod priori
reno
parents: 12
diff changeset
   270
a4be0b8a905d bug fix : can view own comment on comment add on mod priori
reno
parents: 12
diff changeset
   271
        if text_version.mod_posteriori or has_perm(request, 'can_view_unapproved_comment', text=text) or has_perm(request, 'can_view_comment_own', text=text) : 
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   272
            ret['comment'] = comment
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   273
            ret['msg'] = _(u"comment saved")
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   274
        else :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   275
            ret['msg'] = _(u"comment saved, it is being held for moderation")
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   276
        
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   277
        if AUTO_CONTRIB_REGISTER:
12
f69ff46d3240 various notification changes
reno
parents: 0
diff changeset
   278
            Notification.objects.set_notification(text=text, type='own', active=True, email_or_user=user or email)            
0
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   279
        register_activity(request, "comment_created", text, comment)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   280
    return ret
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   281
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   282
#we need to call comments_thread from here this function will be very expensive 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   283
# TODO: stupid get rid of text argument
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   284
def get_filter_datas(request, text_version, text):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   285
    from django.db.models import Count
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   286
    from datetime import datetime, timedelta
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   287
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   288
    allowed_ids = [c.id for c in comments_thread(request, text_version, text)] 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   289
    allowed_comments = Comment.objects.filter(Q(text_version=text_version),Q(deleted=False),Q(id__in=allowed_ids)) 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   290
    #print allowed_ids 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   291
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   292
    # authors
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   293
#    names = list(Comment.objects.filter(text_version__text__key=key).filter(user__isnull=True).values('name').annotate(nb_comments=Count('id'))) #.order_by('name'))
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   294
    names = list(allowed_comments.filter(user__isnull=True).values('name').annotate(nb_comments=Count('id'))) #.order_by('name'))
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   295
    names += list(User.objects.filter(Q(comment__text_version=text_version),Q(comment__deleted=False), Q(comment__id__in=allowed_ids)).extra(select={'name': "username"}).values('name').annotate(nb_comments=Count('id'))) #.order_by('username'))
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   296
    names.sort(key = lambda obj:obj["name"])
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   297
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   298
    # dates
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   299
    # TODO maybe optimize by comparing dates in python and saving these 'by day db requests'
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   300
    nb_days = [1, 3, 7, 30]
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   301
    dates = []
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   302
    today = datetime.today()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   303
    for nb_day in nb_days :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   304
        day_date = today - timedelta(nb_day)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   305
        dates.append({'nb_day' : nb_day, 'nb_day_date':datetime_to_epoch(day_date), 'nb_comments':allowed_comments.filter(modified__gt = day_date).count()})
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   306
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   307
    # tags
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   308
    comment_ids = [c.id for c in allowed_comments]
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   309
    tags = list(Tag.objects.filter(items__content_type = ContentType.objects.get_for_model(Comment),items__object_id__in=comment_ids).values("name").annotate(nb_comments=Count('id')).distinct().order_by('name'))
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   310
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   311
    # states
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   312
    states = []
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   313
    for state in comment_states :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   314
        states.append({'state' : state, 'nb_comments':allowed_comments.filter(state = state).count()})
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   315
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   316
    return {'names':names, 'dates':dates, 'tags':tags, 'states':states}
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   317
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   318
#def get_ordered_ids(text_version_id):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   319
#    comments_and_replies = Comment.objects.filter(text_version__id=text_version_id)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   320
#    comments = comments_and_replies.filter(reply_to__isnull=True)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   321
#    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   322
#    dic = {}
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   323
#    for c in comments_and_replies :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   324
#        top_comment = c.top_comment()
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   325
#        max_modif = dic.get(top_comment.id, c.modified)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   326
#        dic[top_comment.id] = c.modified if max_modif < c.modified else max_modif
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   327
#    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   328
#    ordered_comment_ids = {'scope' : [c.id for c in comments.order_by('start_wrapper','start_offset','end_offset')],
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   329
#                           'thread_modified' : map(operator.itemgetter(0), sorted(dic.items(), key=operator.itemgetter(1)))}
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   330
#    return ordered_comment_ids
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   331
   
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   332
def validate_tags(tags):
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   333
    if tags :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   334
        try :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   335
            if len(tags) > 250 : 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   336
                return _(u"Tags input must be no longer than 250 characters.")
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   337
            TagField().formfield().clean(tags)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   338
        except ValidationError, e :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   339
            return ",".join(e.messages) 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   340
    return ''
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   341
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   342
MAX_NB_TAGS_IN_COMMENT_CLOUD = 30
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   343
def get_tagcloud(key) :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   344
    tagCloud = Tag.objects.cloud_for_model(Comment, steps=8, distribution=LOGARITHMIC, filters=dict(text_version__text__key=key))
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   345
    return tagCloud
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   346
    
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   347
# returns a flat list of viewable comments and their replies ordered as they should be : 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   348
# order is : 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   349
# 'start_wrapper','start_offset','end_wrapper','end_offset' for 'real' comments
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   350
# 'created' for replies
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   351
# TODO: get rid of text here, keep text_version
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   352
def comments_thread(request, text_version, text) : 
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   353
    commentsnoreply = text_version.comment_set.filter(reply_to__isnull=True)#id=3)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   354
    viewable_commentsnoreply = get_viewable_comments(request, commentsnoreply, text, order_by = ('start_wrapper','start_offset','end_wrapper','end_offset'))
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   355
    viewable_comments = []
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   356
    for cc in viewable_commentsnoreply :
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   357
        viewable_comments += list_viewable_comments(request, [cc], text)
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   358
    return viewable_comments
40c8f766c9b8 import from internal svn r 4007
raph
parents:
diff changeset
   359