Commit caf99954c6e522018b30088a78ff416796e00e18

Authored by Sergio Oliveira
2 parents b3223441 9857e341

Merge pull request #126 from TracyWebTech/fixing_by_stmts

Fixing by stmts
src/proxy/migrations/0005_adding_modified_by.py 0 → 100644
@@ -0,0 +1,125 @@ @@ -0,0 +1,125 @@
  1 +# -*- coding: utf-8 -*-
  2 +import datetime
  3 +from django.db import connections
  4 +from south.db import db
  5 +from south.v2 import DataMigration
  6 +from django.db import models
  7 +
  8 +class Migration(DataMigration):
  9 +
  10 + def forwards(self, orm):
  11 + # Selecting trac database
  12 + connection = connections['trac']
  13 +
  14 + cursor = connection.cursor()
  15 + cursor.execute('''
  16 + CREATE OR REPLACE VIEW wiki_view AS SELECT
  17 + wiki.name AS name,
  18 + (SELECT wiki2.text FROM wiki AS wiki2 WHERE wiki2.name = wiki.name
  19 + AND wiki2.version = MAX(wiki.version)) AS wiki_text,
  20 + (SELECT wiki3.author FROM wiki AS wiki3 WHERE wiki3.name = wiki.name
  21 + AND wiki3.version = 1) AS author,
  22 + string_agg(DISTINCT wiki.author, ', ') AS collaborators,
  23 + TIMESTAMP WITH TIME ZONE 'epoch' + (MIN(wiki.time)/1000000) * INTERVAL '1s' AS created,
  24 + TIMESTAMP WITH TIME ZONE 'epoch' + (MAX(wiki.time)/1000000) * INTERVAL '1s' AS modified,
  25 + (SELECT wiki4.author FROM wiki AS wiki4 WHERE wiki4.name = wiki.name
  26 + AND wiki4.version = MAX(wiki.version)) AS modified_by
  27 + FROM wiki
  28 + GROUP BY wiki.name;
  29 +
  30 + CREATE OR REPLACE VIEW ticket_view AS SELECT
  31 + ticket.id AS id,
  32 + ticket.summary as summary,
  33 + ticket.description as description,
  34 + ticket.milestone as milestone,
  35 + ticket.priority as priority,
  36 + ticket.component as component,
  37 + ticket.version as version,
  38 + ticket.severity as severity,
  39 + ticket.reporter as reporter,
  40 + ticket.reporter as author,
  41 + ticket.status as status,
  42 + ticket.keywords as keywords,
  43 + (SELECT
  44 + string_agg(DISTINCT ticket_change.author, ', ')
  45 + FROM ticket_change WHERE ticket_change.ticket = ticket.id
  46 + GROUP BY ticket_change.ticket) as collaborators,
  47 + TIMESTAMP WITH TIME ZONE 'epoch' + (time/1000000)* INTERVAL '1s' AS created,
  48 + TIMESTAMP WITH TIME ZONE 'epoch' + (changetime/1000000) * INTERVAL '1s' AS modified,
  49 + (SELECT
  50 + ticket_change.author
  51 + FROM ticket_change
  52 + WHERE ticket_change.ticket = ticket.id
  53 + AND ticket_change.time = ticket.changetime
  54 + LIMIT 1
  55 + ) AS modified_by
  56 + FROM ticket;
  57 + ''')
  58 +
  59 +
  60 + def backwards(self, orm):
  61 + # Selecting trac database
  62 + connection = connections['trac']
  63 +
  64 + cursor = connection.cursor()
  65 + cursor.execute('''
  66 + ALTER VIEW wiki_view ALTER COLUMN modified_by DROP DEFAULT;
  67 + ALTER VIEW ticket_view ALTER COLUMN modified_by DROP DEFAULT;
  68 + ''')
  69 +
  70 +
  71 + models = {
  72 + u'proxy.attachment': {
  73 + 'Meta': {'object_name': 'Attachment', 'db_table': "'attachment_view'", 'managed': 'False'},
  74 + 'attach_id': ('django.db.models.fields.TextField', [], {}),
  75 + 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  76 + 'created': ('django.db.models.fields.DateTimeField', [], {'blank': 'True'}),
  77 + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  78 + 'filename': ('django.db.models.fields.TextField', [], {}),
  79 + 'mimetype': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  80 + 'size': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
  81 + 'url': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}),
  82 + 'used_by': ('django.db.models.fields.TextField', [], {})
  83 + },
  84 + u'proxy.revision': {
  85 + 'Meta': {'object_name': 'Revision', 'db_table': "'revision_view'", 'managed': 'False'},
  86 + 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  87 + 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
  88 + 'key': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}),
  89 + 'message': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  90 + 'repository_name': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  91 + 'rev': ('django.db.models.fields.TextField', [], {'blank': 'True'})
  92 + },
  93 + u'proxy.ticket': {
  94 + 'Meta': {'object_name': 'Ticket', 'db_table': "'ticket_view'", 'managed': 'False'},
  95 + 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  96 + 'collaborators': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  97 + 'component': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  98 + 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
  99 + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  100 + 'id': ('django.db.models.fields.IntegerField', [], {'primary_key': 'True'}),
  101 + 'keywords': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  102 + 'milestone': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  103 + 'modified': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
  104 + 'modified_by': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  105 + 'priority': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  106 + 'reporter': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  107 + 'severity': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  108 + 'status': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  109 + 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  110 + 'version': ('django.db.models.fields.TextField', [], {'blank': 'True'})
  111 + },
  112 + u'proxy.wiki': {
  113 + 'Meta': {'object_name': 'Wiki', 'db_table': "'wiki_view'", 'managed': 'False'},
  114 + 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  115 + 'collaborators': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  116 + 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
  117 + 'modified': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
  118 + 'modified_by': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  119 + 'name': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}),
  120 + 'wiki_text': ('django.db.models.fields.TextField', [], {'blank': 'True'})
  121 + }
  122 + }
  123 +
  124 + complete_apps = ['proxy']
  125 + symmetrical = True
src/proxy/models.py
@@ -81,6 +81,7 @@ class Ticket(models.Model, HitCounterModelMixin): @@ -81,6 +81,7 @@ class Ticket(models.Model, HitCounterModelMixin):
81 collaborators = models.TextField(blank=True) 81 collaborators = models.TextField(blank=True)
82 created = models.DateTimeField(blank=True, null=True) 82 created = models.DateTimeField(blank=True, null=True)
83 modified = models.DateTimeField(blank=True, null=True) 83 modified = models.DateTimeField(blank=True, null=True)
  84 + modified_by = models.TextField(blank=True)
84 85
85 class Meta: 86 class Meta:
86 managed = False 87 managed = False
@@ -95,6 +96,12 @@ class Ticket(models.Model, HitCounterModelMixin): @@ -95,6 +96,12 @@ class Ticket(models.Model, HitCounterModelMixin):
95 except User.DoesNotExist: 96 except User.DoesNotExist:
96 return None 97 return None
97 98
  99 + def get_modified_by(self):
  100 + try:
  101 + return User.objects.get(username=self.modified_by)
  102 + except User.DoesNotExist:
  103 + return None
  104 +
98 105
99 class Wiki(models.Model, HitCounterModelMixin): 106 class Wiki(models.Model, HitCounterModelMixin):
100 name = models.TextField(primary_key=True) 107 name = models.TextField(primary_key=True)
@@ -103,6 +110,7 @@ class Wiki(models.Model, HitCounterModelMixin): @@ -103,6 +110,7 @@ class Wiki(models.Model, HitCounterModelMixin):
103 collaborators = models.TextField(blank=True) 110 collaborators = models.TextField(blank=True)
104 created = models.DateTimeField(blank=True, null=True) 111 created = models.DateTimeField(blank=True, null=True)
105 modified = models.DateTimeField(blank=True, null=True) 112 modified = models.DateTimeField(blank=True, null=True)
  113 + modified_by = models.TextField(blank=True)
106 114
107 class Meta: 115 class Meta:
108 managed = False 116 managed = False
@@ -116,3 +124,9 @@ class Wiki(models.Model, HitCounterModelMixin): @@ -116,3 +124,9 @@ class Wiki(models.Model, HitCounterModelMixin):
116 return User.objects.get(username=self.author) 124 return User.objects.get(username=self.author)
117 except User.DoesNotExist: 125 except User.DoesNotExist:
118 return None 126 return None
  127 +
  128 + def get_modified_by(self):
  129 + try:
  130 + return User.objects.get(username=self.modified_by)
  131 + except User.DoesNotExist:
  132 + return None
src/search/base_indexes.py
@@ -19,6 +19,8 @@ class BaseIndex(indexes.SearchIndex): @@ -19,6 +19,8 @@ class BaseIndex(indexes.SearchIndex):
19 icon_name = indexes.CharField(indexed=False) 19 icon_name = indexes.CharField(indexed=False)
20 fullname_and_username = indexes.CharField(null=True, stored=False) 20 fullname_and_username = indexes.CharField(null=True, stored=False)
21 hits = indexes.IntegerField(model_attr='hits') 21 hits = indexes.IntegerField(model_attr='hits')
  22 + modified_by = indexes.CharField(null=True)
  23 + modified_by_url = indexes.CharField(null=True)
22 24
23 def get_updated_field(self): 25 def get_updated_field(self):
24 return 'modified' 26 return 'modified'
@@ -40,6 +42,24 @@ class BaseIndex(indexes.SearchIndex): @@ -40,6 +42,24 @@ class BaseIndex(indexes.SearchIndex):
40 return author.username 42 return author.username
41 return obj.author 43 return obj.author
42 44
  45 + def prepare_author_url(self, obj):
  46 + author = obj.get_author()
  47 + if author:
  48 + return author.get_absolute_url()
  49 + return None
  50 +
  51 + def prepare_fullname(self, obj):
  52 + if hasattr(obj, 'modified_by'):
  53 + modified_by = obj.get_modified_by()
  54 + if modified_by:
  55 + return modified_by.get_full_name()
  56 + return None
  57 + else:
  58 + author = obj.get_author()
  59 + if author:
  60 + return author.get_full_name()
  61 + return obj.author
  62 +
43 def prepare_fullname_and_username(self, obj): 63 def prepare_fullname_and_username(self, obj):
44 author = obj.get_author() 64 author = obj.get_author()
45 if not author: 65 if not author:
@@ -49,14 +69,14 @@ class BaseIndex(indexes.SearchIndex): @@ -49,14 +69,14 @@ class BaseIndex(indexes.SearchIndex):
49 author.username, 69 author.username,
50 ) 70 )
51 71
52 - def prepare_author_url(self, obj):  
53 - author = obj.get_author()  
54 - if author:  
55 - return author.get_absolute_url() 72 + def prepare_modified_by(self, obj):
  73 + if hasattr(obj, 'modified_by'):
  74 + return obj.modified_by
56 return None 75 return None
57 76
58 - def prepare_fullname(self, obj):  
59 - author = obj.get_author()  
60 - if author:  
61 - return author.get_full_name()  
62 - return obj.author 77 + def prepare_modified_by_url(self, obj):
  78 + if hasattr(obj, 'modified_by'):
  79 + modified_by = obj.get_modified_by()
  80 + if modified_by:
  81 + return modified_by.get_absolute_url()
  82 + return None
src/super_archives/models.py
@@ -326,9 +326,12 @@ class Message(models.Model): @@ -326,9 +326,12 @@ class Message(models.Model):
326 326
327 @property 327 @property
328 def author(self): 328 def author(self):
329 - from_address = self.from_address  
330 - if from_address.user:  
331 - return from_address.user.username 329 + return self.fullname
  330 +
  331 + @property
  332 + def author_url(self):
  333 + if self.from_address.user_id:
  334 + return self.from_address.user.get_absolute_url()
332 return None 335 return None
333 336
334 @property 337 @property
@@ -336,10 +339,6 @@ class Message(models.Model): @@ -336,10 +339,6 @@ class Message(models.Model):
336 return self.from_address.get_full_name() 339 return self.from_address.get_full_name()
337 340
338 @property 341 @property
339 - def author_url(self):  
340 - return self.from_address.user.get_absolute_url()  
341 -  
342 - @property  
343 def icon_name(self): 342 def icon_name(self):
344 return u'envelope' 343 return u'envelope'
345 344
src/super_archives/search_indexes.py
@@ -58,9 +58,18 @@ class ThreadIndex(BaseIndex, indexes.Indexable): @@ -58,9 +58,18 @@ class ThreadIndex(BaseIndex, indexes.Indexable):
58 return first_message.from_address.user.get_absolute_url() 58 return first_message.from_address.user.get_absolute_url()
59 return None 59 return None
60 60
  61 + def prepare_modified_by(self, obj):
  62 + return obj.latest_message.author
  63 +
  64 + def prepare_modified_by_url(self, obj):
  65 + return obj.latest_message.author_url
  66 +
61 def prepare_created(self, obj): 67 def prepare_created(self, obj):
62 return obj.message_set.first().received_time 68 return obj.message_set.first().received_time
63 69
  70 + def prepare_fullname(self, obj):
  71 + return obj.latest_message.from_address.get_full_name()
  72 +
64 def prepare_icon_name(self, obj): 73 def prepare_icon_name(self, obj):
65 return u'envelope' 74 return u'envelope'
66 75
src/super_archives/templates/message-preview.html
@@ -36,22 +36,28 @@ @@ -36,22 +36,28 @@
36 </span> 36 </span>
37 {% endif %} 37 {% endif %}
38 38
39 -{% if result.fullname or result.modified %} 39 +{% if result.fullname or result.modified or result.modified_by %}
40 <div class="quiet"> 40 <div class="quiet">
41 - {% if result.fullname %} 41 + {% if result.fullname or result.modified_by %}
42 <span class="pull-left">{% trans "by" %} 42 <span class="pull-left">{% trans "by" %}
43 - {% if result.fullname and result.author_url %}  
44 - <a href="{{ result.author_url }}"> 43 + {% if result.fullname and result.author_url or result.modified_by and result.modified_by_url %}
  44 + <a href="{% firstof result.modified_by_url result.author_url %}">
45 {% if query %} 45 {% if query %}
46 - {% highlight result.fullname with query %} 46 + {% if result.modified_by %}
  47 + {% highlight result.modified_by with query %}
  48 + {% else %}
  49 + {% highlight result.fullname with query %}
  50 + {% endif %}
47 {% else %} 51 {% else %}
48 - {{ result.fullname }} 52 + {% firstof result.modified_by result.fullname %}
49 {% endif %} 53 {% endif %}
50 </a> 54 </a>
51 {% else %} 55 {% else %}
52 <span>{{ result.fullname }}</span> 56 <span>{{ result.fullname }}</span>
53 {% endif %} 57 {% endif %}
54 </span> 58 </span>
  59 + {% else %}
  60 + <span class="pull-left">{% trans "by" %} {% trans "Anonymous" %}</span>
55 {% endif %} 61 {% endif %}
56 {% if result.modified %} 62 {% if result.modified %}
57 <span class="pull-right">{{ result.modified|localtime|timesince }} {% trans "ago" %}</span> 63 <span class="pull-right">{{ result.modified|localtime|timesince }} {% trans "ago" %}</span>