Commit b3108e39972cb29c7da6cf724e74fc6bbf1269bb

Authored by Gust
1 parent 1e7861da

Fixing and extracting Trac dependencies

-Trac filters and search options only show if trac enabled
-Chart only shows trac data if enabled
-Fix rollback migration of Trac

Signed-off-by: Gustavo Jaruga <darksshades@gmail.com>
Signed-off-by: Matheus Faria <matheus.sousa.faria@gmail.com>
src/accounts/search_indexes.py
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 from haystack import indexes 3 from haystack import indexes
4 from django.db.models import Count 4 from django.db.models import Count
5 5
6 -from proxy.trac.models import Revision, Ticket, Wiki 6 +from proxy.models import Revision, Ticket, Wiki
7 from badger.utils import get_users_counters 7 from badger.utils import get_users_counters
8 from .models import User 8 from .models import User
9 9
src/accounts/views.py
@@ -25,7 +25,7 @@ from haystack.query import SearchQuerySet @@ -25,7 +25,7 @@ from haystack.query import SearchQuerySet
25 from super_archives.models import EmailAddress, Message 25 from super_archives.models import EmailAddress, Message
26 from super_archives.utils.email import send_email_lists 26 from super_archives.utils.email import send_email_lists
27 from search.utils import trans 27 from search.utils import trans
28 -from proxy.trac.models import WikiCollabCount, TicketCollabCount 28 +from proxy.models import WikiCollabCount, TicketCollabCount
29 from .forms import (UserCreationForm, ListsForm, UserUpdateForm, 29 from .forms import (UserCreationForm, ListsForm, UserUpdateForm,
30 ChangeXMPPPasswordForm) 30 ChangeXMPPPasswordForm)
31 from .errors import XMPPChangePwdException 31 from .errors import XMPPChangePwdException
src/api/resources.py
@@ -7,7 +7,7 @@ from tastypie.constants import ALL_WITH_RELATIONS, ALL @@ -7,7 +7,7 @@ from tastypie.constants import ALL_WITH_RELATIONS, ALL
7 from tastypie.resources import ModelResource 7 from tastypie.resources import ModelResource
8 8
9 from super_archives.models import Message, EmailAddress 9 from super_archives.models import Message, EmailAddress
10 -from proxy.trac.models import Revision, Ticket, Wiki 10 +from proxy.models import Revision, Ticket, Wiki
11 11
12 12
13 User = get_user_model() 13 User = get_user_model()
src/badger/utils.py
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 2
3 from django.db.models import Count 3 from django.db.models import Count
4 4
5 -from proxy.trac.models import (Revision, Ticket, Wiki, 5 +from proxy.models import (Revision, Ticket, Wiki,
6 WikiCollabCount, TicketCollabCount) 6 WikiCollabCount, TicketCollabCount)
7 from accounts.models import User 7 from accounts.models import User
8 8
src/colab/custom_settings.py
@@ -255,18 +255,6 @@ MESSAGE_TAGS = { @@ -255,18 +255,6 @@ MESSAGE_TAGS = {
255 messages.ERROR: 'alert-danger', 255 messages.ERROR: 'alert-danger',
256 } 256 }
257 257
258 -  
259 -### Trac  
260 -TRAC_ENABLED = False  
261 -  
262 -if TRAC_ENABLED:  
263 - from trac_settings import *  
264 - DATABASES['trac'] = TRAC_DATABASE  
265 - INSTALLED_APPS = INSTALLED_APPS + (  
266 - 'proxy.trac',  
267 - )  
268 -  
269 -  
270 ### Feedzilla (planet) 258 ### Feedzilla (planet)
271 from feedzilla.settings import * 259 from feedzilla.settings import *
272 FEEDZILLA_PAGE_SIZE = 5 260 FEEDZILLA_PAGE_SIZE = 5
@@ -321,7 +309,19 @@ DPASTE_EXPIRE_DEFAULT = DPASTE_EXPIRE_CHOICES[4][0] @@ -321,7 +309,19 @@ DPASTE_EXPIRE_DEFAULT = DPASTE_EXPIRE_CHOICES[4][0]
321 DPASTE_DEFAULT_GIST_DESCRIPTION = 'Gist created on Colab Interlegis' 309 DPASTE_DEFAULT_GIST_DESCRIPTION = 'Gist created on Colab Interlegis'
322 DPASTE_DEFAULT_GIST_NAME = 'colab_paste' 310 DPASTE_DEFAULT_GIST_NAME = 'colab_paste'
323 311
  312 +
  313 +### Trac
  314 +TRAC_ENABLED = False
  315 +
  316 +from trac_settings import *
  317 +DATABASES['trac'] = TRAC_DATABASE
  318 +
324 try: 319 try:
325 from local_settings import * 320 from local_settings import *
326 except ImportError: 321 except ImportError:
327 pass 322 pass
  323 +
  324 +if TRAC_ENABLED:
  325 + INSTALLED_APPS = INSTALLED_APPS + (
  326 + 'proxy.trac',
  327 + )
328 \ No newline at end of file 328 \ No newline at end of file
src/home/views.py
@@ -9,7 +9,7 @@ from django.http import HttpResponse, Http404 @@ -9,7 +9,7 @@ from django.http import HttpResponse, Http404
9 from search.utils import trans 9 from search.utils import trans
10 from haystack.query import SearchQuerySet 10 from haystack.query import SearchQuerySet
11 11
12 -from proxy.trac.models import WikiCollabCount, TicketCollabCount 12 +from proxy.models import WikiCollabCount, TicketCollabCount
13 from super_archives.models import Thread 13 from super_archives.models import Thread
14 14
15 15
@@ -23,12 +23,16 @@ def index(request): @@ -23,12 +23,16 @@ def index(request):
23 count_types = cache.get('home_chart') 23 count_types = cache.get('home_chart')
24 if count_types is None: 24 if count_types is None:
25 count_types = OrderedDict() 25 count_types = OrderedDict()
26 - for type in ['thread', 'changeset', 'attachment']:  
27 - count_types[type] = SearchQuerySet().filter(  
28 - type=type,  
29 - ).count() 26 + count_types['thread'] = SearchQuerySet().filter(
  27 + type='thread',
  28 + ).count()
30 29
31 if settings.TRAC_ENABLED: 30 if settings.TRAC_ENABLED:
  31 + for type in ['changeset', 'attachment']:
  32 + count_types[type] = SearchQuerySet().filter(
  33 + type=type,
  34 + ).count()
  35 +
32 count_types['ticket'] = sum([ 36 count_types['ticket'] = sum([
33 ticket.count for ticket in TicketCollabCount.objects.all() 37 ticket.count for ticket in TicketCollabCount.objects.all()
34 ]) 38 ])
src/proxy/models.py
1 # -*- coding: utf-8 -*- 1 # -*- coding: utf-8 -*-
2 from django.db import models 2 from django.db import models
3 from django.conf import settings 3 from django.conf import settings
  4 +import os
  5 +import urllib2
4 6
5 -if settings.TRAC_ENABLED:  
6 - import trac.trac.models 7 +from django.conf import settings
  8 +from django.db import models, connections
  9 +from django.db.models.signals import post_save
  10 +from django.dispatch import receiver
  11 +
  12 +from accounts.models import User
  13 +from hitcounter.models import HitCounterModelMixin
  14 +
  15 +class Attachment(models.Model, HitCounterModelMixin):
  16 + url = models.TextField(primary_key=True)
  17 + attach_id = models.TextField()
  18 + used_by = models.TextField()
  19 + filename = models.TextField()
  20 + author = models.TextField(blank=True)
  21 + description = models.TextField(blank=True)
  22 + created = models.DateTimeField(blank=True)
  23 + mimetype = models.TextField(blank=True)
  24 + size = models.IntegerField(blank=True)
  25 +
  26 + class Meta:
  27 + managed = False
  28 + db_table = 'attachment_view'
  29 +
  30 + @property
  31 + def filepath(self):
  32 + return os.path.join(
  33 + settings.ATTACHMENTS_FOLDER_PATH,
  34 + self.used_by,
  35 + self.attach_id,
  36 + urllib2.quote(self.filename.encode('utf8'))
  37 + )
  38 +
  39 + def get_absolute_url(self):
  40 + return u'/raw-attachment/{}'.format(self.url)
  41 +
  42 + def get_author(self):
  43 + try:
  44 + return User.objects.get(username=self.author)
  45 + except User.DoesNotExist:
  46 + return None
  47 +
  48 +
  49 +class Revision(models.Model, HitCounterModelMixin):
  50 + key = models.TextField(blank=True, primary_key=True)
  51 + rev = models.TextField(blank=True)
  52 + author = models.TextField(blank=True)
  53 + message = models.TextField(blank=True)
  54 + repository_name = models.TextField(blank=True)
  55 + created = models.DateTimeField(blank=True, null=True)
  56 +
  57 + class Meta:
  58 + managed = False
  59 + db_table = 'revision_view'
  60 +
  61 + def get_absolute_url(self):
  62 + return u'/changeset/{}/{}'.format(self.rev, self.repository_name)
  63 +
  64 + def get_author(self):
  65 + try:
  66 + return User.objects.get(username=self.author)
  67 + except User.DoesNotExist:
  68 + return None
  69 +
  70 +class Ticket(models.Model, HitCounterModelMixin):
  71 + id = models.IntegerField(primary_key=True)
  72 + summary = models.TextField(blank=True)
  73 + description = models.TextField(blank=True)
  74 + milestone = models.TextField(blank=True)
  75 + priority = models.TextField(blank=True)
  76 + component = models.TextField(blank=True)
  77 + version = models.TextField(blank=True)
  78 + severity = models.TextField(blank=True)
  79 + reporter = models.TextField(blank=True)
  80 + author = models.TextField(blank=True)
  81 + status = models.TextField(blank=True)
  82 + keywords = models.TextField(blank=True)
  83 + collaborators = models.TextField(blank=True)
  84 + created = models.DateTimeField(blank=True, null=True)
  85 + modified = models.DateTimeField(blank=True, null=True)
  86 + modified_by = models.TextField(blank=True)
  87 +
  88 + class Meta:
  89 + managed = False
  90 + db_table = 'ticket_view'
  91 +
  92 + def get_absolute_url(self):
  93 + return u'/ticket/{}'.format(self.id)
  94 +
  95 + def get_author(self):
  96 + try:
  97 + return User.objects.get(username=self.author)
  98 + except User.DoesNotExist:
  99 + return None
  100 +
  101 + def get_modified_by(self):
  102 + try:
  103 + return User.objects.get(username=self.modified_by)
  104 + except User.DoesNotExist:
  105 + return None
  106 +
  107 +class Wiki(models.Model, HitCounterModelMixin):
  108 + name = models.TextField(primary_key=True)
  109 + wiki_text = models.TextField(blank=True)
  110 + author = models.TextField(blank=True)
  111 + collaborators = models.TextField(blank=True)
  112 + created = models.DateTimeField(blank=True, null=True)
  113 + modified = models.DateTimeField(blank=True, null=True)
  114 + modified_by = models.TextField(blank=True)
  115 +
  116 + class Meta:
  117 + managed = False
  118 + db_table = 'wiki_view'
  119 +
  120 + def get_absolute_url(self):
  121 + return u'/wiki/{}'.format(self.name)
  122 +
  123 + def get_author(self):
  124 + try:
  125 + return User.objects.get(username=self.author)
  126 + except User.DoesNotExist:
  127 + return None
  128 +
  129 + def get_modified_by(self):
  130 + try:
  131 + return User.objects.get(username=self.modified_by)
  132 + except User.DoesNotExist:
  133 + return None
  134 +
  135 +
  136 +class WikiCollabCount(models.Model):
  137 + author = models.TextField(primary_key=True)
  138 + count = models.IntegerField()
  139 +
  140 + class Meta:
  141 + managed = False
  142 + db_table = 'wiki_collab_count_view'
  143 +
  144 +
  145 +class TicketCollabCount(models.Model):
  146 + author = models.TextField(primary_key=True)
  147 + count = models.IntegerField()
  148 +
  149 + class Meta:
  150 + managed = False
  151 + db_table = 'ticket_collab_count_view'
  152 +
  153 +
  154 +@receiver(post_save, sender=User)
  155 +def change_session_attribute_email(sender, instance, **kwargs):
  156 + cursor = connections['trac'].cursor()
  157 +
  158 + cursor.execute(("UPDATE session_attribute SET value=%s "
  159 + "WHERE name='email' AND sid=%s"),
  160 + [instance.email, instance.username])
  161 + cursor.execute(("UPDATE session_attribute SET value=%s "
  162 + "WHERE name='name' AND sid=%s"),
  163 + [instance.get_full_name(), instance.username])
  164 +
  165 + cursor.execute(("INSERT INTO session_attribute "
  166 + "(sid, authenticated, name, value) "
  167 + "SELECT %s, '1', 'email', %s WHERE NOT EXISTS "
  168 + "(SELECT 1 FROM session_attribute WHERE sid=%s "
  169 + "AND name='email')"),
  170 + [instance.username, instance.email, instance.username])
  171 +
  172 + cursor.execute(("INSERT INTO session_attribute "
  173 + "(sid, authenticated, name, value) "
  174 + "SELECT %s, '1', 'name', %s WHERE NOT EXISTS "
  175 + "(SELECT 1 FROM session_attribute WHERE sid=%s "
  176 + "AND name='name')"),
  177 + [instance.username, instance.get_full_name(),
  178 + instance.username])
src/proxy/search_indexes.py
@@ -9,7 +9,7 @@ from haystack import indexes @@ -9,7 +9,7 @@ from haystack import indexes
9 from haystack.utils import log as logging 9 from haystack.utils import log as logging
10 10
11 from search.base_indexes import BaseIndex 11 from search.base_indexes import BaseIndex
12 -from trac.models import Attachment, Ticket, Wiki, Revision 12 +from proxy.models import Attachment, Ticket, Wiki, Revision
13 13
14 14
15 logger = logging.getLogger('haystack') 15 logger = logging.getLogger('haystack')
src/proxy/trac/migrations/0001_initial.py
@@ -9,7 +9,7 @@ from django.db import models @@ -9,7 +9,7 @@ from django.db import models
9 class Migration(SchemaMigration): 9 class Migration(SchemaMigration):
10 10
11 def forwards(self, orm): 11 def forwards(self, orm):
12 - connection = connections['trac'] 12 + connection = connections['trac']
13 13
14 cursor = connection.cursor() 14 cursor = connection.cursor()
15 cursor.execute(''' 15 cursor.execute('''
@@ -60,111 +60,111 @@ class Migration(SchemaMigration): @@ -60,111 +60,111 @@ class Migration(SchemaMigration):
60 ); 60 );
61 ''') 61 ''')
62 cursor.execute(''' 62 cursor.execute('''
63 -CREATE OR REPLACE VIEW revision_view AS SELECT  
64 -revision.rev,  
65 -revision.author,  
66 -revision.message,  
67 -repository.value AS repository_name,  
68 -TIMESTAMP WITH TIME ZONE 'epoch' + (revision.time/1000000) * INTERVAL '1s' AS created,  
69 -CONCAT(revision.repos, '-', revision.rev) AS key  
70 -FROM revision  
71 -INNER JOIN repository ON(  
72 -repository.id = revision.repos  
73 -AND repository.name = 'name'  
74 -AND repository.value != ''  
75 -);  
76 -''') 63 + CREATE OR REPLACE VIEW revision_view AS SELECT
  64 + revision.rev,
  65 + revision.author,
  66 + revision.message,
  67 + repository.value AS repository_name,
  68 + TIMESTAMP WITH TIME ZONE 'epoch' + (revision.time/1000000) * INTERVAL '1s' AS created,
  69 + CONCAT(revision.repos, '-', revision.rev) AS key
  70 + FROM revision
  71 + INNER JOIN repository ON(
  72 + repository.id = revision.repos
  73 + AND repository.name = 'name'
  74 + AND repository.value != ''
  75 + );
  76 + ''')
77 cursor.execute(''' 77 cursor.execute('''
78 -CREATE OR REPLACE VIEW attachment_view AS SELECT  
79 -CONCAT(attachment.type, '/' , attachment.id, '/', attachment.filename) AS url,  
80 -attachment.type AS used_by,  
81 -attachment.filename AS filename,  
82 -attachment.id as attach_id,  
83 -(SELECT LOWER(SUBSTRING(attachment.filename FROM '\.(\w+)$'))) AS mimetype,  
84 -attachment.author AS author,  
85 -attachment.description AS description,  
86 -attachment.size AS size,  
87 -TIMESTAMP WITH TIME ZONE 'epoch' + (attachment.time/1000000)* INTERVAL '1s' AS created  
88 -FROM attachment;  
89 -''') 78 + CREATE OR REPLACE VIEW attachment_view AS SELECT
  79 + CONCAT(attachment.type, '/' , attachment.id, '/', attachment.filename) AS url,
  80 + attachment.type AS used_by,
  81 + attachment.filename AS filename,
  82 + attachment.id as attach_id,
  83 + (SELECT LOWER(SUBSTRING(attachment.filename FROM '\.(\w+)$'))) AS mimetype,
  84 + attachment.author AS author,
  85 + attachment.description AS description,
  86 + attachment.size AS size,
  87 + TIMESTAMP WITH TIME ZONE 'epoch' + (attachment.time/1000000)* INTERVAL '1s' AS created
  88 + FROM attachment;
  89 + ''')
90 cursor.execute(''' 90 cursor.execute('''
91 -CREATE OR REPLACE VIEW wiki_view AS SELECT  
92 -wiki.name AS name,  
93 -(SELECT wiki2.text FROM wiki AS wiki2 WHERE wiki2.name = wiki.name  
94 -AND wiki2.version = MAX(wiki.version)) AS wiki_text,  
95 -(SELECT wiki3.author FROM wiki AS wiki3 WHERE wiki3.name = wiki.name  
96 -AND wiki3.version = 1) AS author,  
97 -string_agg(DISTINCT wiki.author, ', ') AS collaborators,  
98 -TIMESTAMP WITH TIME ZONE 'epoch' + (MIN(wiki.time)/1000000) * INTERVAL '1s' AS created,  
99 -TIMESTAMP WITH TIME ZONE 'epoch' + (MAX(wiki.time)/1000000) * INTERVAL '1s' AS modified  
100 -FROM wiki  
101 -GROUP BY wiki.name;  
102 -''') 91 + CREATE OR REPLACE VIEW wiki_view AS SELECT
  92 + wiki.name AS name,
  93 + (SELECT wiki2.text FROM wiki AS wiki2 WHERE wiki2.name = wiki.name
  94 + AND wiki2.version = MAX(wiki.version)) AS wiki_text,
  95 + (SELECT wiki3.author FROM wiki AS wiki3 WHERE wiki3.name = wiki.name
  96 + AND wiki3.version = 1) AS author,
  97 + string_agg(DISTINCT wiki.author, ', ') AS collaborators,
  98 + TIMESTAMP WITH TIME ZONE 'epoch' + (MIN(wiki.time)/1000000) * INTERVAL '1s' AS created,
  99 + TIMESTAMP WITH TIME ZONE 'epoch' + (MAX(wiki.time)/1000000) * INTERVAL '1s' AS modified
  100 + FROM wiki
  101 + GROUP BY wiki.name;
  102 + ''')
103 cursor.execute(''' 103 cursor.execute('''
104 -CREATE OR REPLACE VIEW wiki_view AS SELECT  
105 -wiki.name AS name,  
106 -(SELECT wiki2.text FROM wiki AS wiki2 WHERE wiki2.name = wiki.name  
107 -AND wiki2.version = MAX(wiki.version)) AS wiki_text,  
108 -(SELECT wiki3.author FROM wiki AS wiki3 WHERE wiki3.name = wiki.name  
109 -AND wiki3.version = 1) AS author,  
110 -string_agg(DISTINCT wiki.author, ', ') AS collaborators,  
111 -TIMESTAMP WITH TIME ZONE 'epoch' + (MIN(wiki.time)/1000000) * INTERVAL '1s' AS created,  
112 -TIMESTAMP WITH TIME ZONE 'epoch' + (MAX(wiki.time)/1000000) * INTERVAL '1s' AS modified,  
113 -(SELECT wiki4.author FROM wiki AS wiki4 WHERE wiki4.name = wiki.name  
114 -AND wiki4.version = MAX(wiki.version)) AS modified_by  
115 -FROM wiki  
116 -GROUP BY wiki.name; 104 + CREATE OR REPLACE VIEW wiki_view AS SELECT
  105 + wiki.name AS name,
  106 + (SELECT wiki2.text FROM wiki AS wiki2 WHERE wiki2.name = wiki.name
  107 + AND wiki2.version = MAX(wiki.version)) AS wiki_text,
  108 + (SELECT wiki3.author FROM wiki AS wiki3 WHERE wiki3.name = wiki.name
  109 + AND wiki3.version = 1) AS author,
  110 + string_agg(DISTINCT wiki.author, ', ') AS collaborators,
  111 + TIMESTAMP WITH TIME ZONE 'epoch' + (MIN(wiki.time)/1000000) * INTERVAL '1s' AS created,
  112 + TIMESTAMP WITH TIME ZONE 'epoch' + (MAX(wiki.time)/1000000) * INTERVAL '1s' AS modified,
  113 + (SELECT wiki4.author FROM wiki AS wiki4 WHERE wiki4.name = wiki.name
  114 + AND wiki4.version = MAX(wiki.version)) AS modified_by
  115 + FROM wiki
  116 + GROUP BY wiki.name;
117 117
118 -CREATE OR REPLACE VIEW ticket_view AS SELECT  
119 -ticket.id AS id,  
120 -ticket.summary as summary,  
121 -ticket.description as description,  
122 -ticket.milestone as milestone,  
123 -ticket.priority as priority,  
124 -ticket.component as component,  
125 -ticket.version as version,  
126 -ticket.severity as severity,  
127 -ticket.reporter as reporter,  
128 -ticket.reporter as author,  
129 -ticket.status as status,  
130 -ticket.keywords as keywords,  
131 -(SELECT  
132 -string_agg(DISTINCT ticket_change.author, ', ')  
133 -FROM ticket_change WHERE ticket_change.ticket = ticket.id  
134 -GROUP BY ticket_change.ticket) as collaborators,  
135 -TIMESTAMP WITH TIME ZONE 'epoch' + (time/1000000)* INTERVAL '1s' AS created,  
136 -TIMESTAMP WITH TIME ZONE 'epoch' + (changetime/1000000) * INTERVAL '1s' AS modified,  
137 -(SELECT  
138 -ticket_change.author  
139 -FROM ticket_change  
140 -WHERE ticket_change.ticket = ticket.id  
141 -AND ticket_change.time = ticket.changetime  
142 -LIMIT 1  
143 -) AS modified_by  
144 -FROM ticket;  
145 -''') 118 + CREATE OR REPLACE VIEW ticket_view AS SELECT
  119 + ticket.id AS id,
  120 + ticket.summary as summary,
  121 + ticket.description as description,
  122 + ticket.milestone as milestone,
  123 + ticket.priority as priority,
  124 + ticket.component as component,
  125 + ticket.version as version,
  126 + ticket.severity as severity,
  127 + ticket.reporter as reporter,
  128 + ticket.reporter as author,
  129 + ticket.status as status,
  130 + ticket.keywords as keywords,
  131 + (SELECT
  132 + string_agg(DISTINCT ticket_change.author, ', ')
  133 + FROM ticket_change WHERE ticket_change.ticket = ticket.id
  134 + GROUP BY ticket_change.ticket) as collaborators,
  135 + TIMESTAMP WITH TIME ZONE 'epoch' + (time/1000000)* INTERVAL '1s' AS created,
  136 + TIMESTAMP WITH TIME ZONE 'epoch' + (changetime/1000000) * INTERVAL '1s' AS modified,
  137 + (SELECT
  138 + ticket_change.author
  139 + FROM ticket_change
  140 + WHERE ticket_change.ticket = ticket.id
  141 + AND ticket_change.time = ticket.changetime
  142 + LIMIT 1
  143 + ) AS modified_by
  144 + FROM ticket;
  145 + ''')
146 cursor.execute(''' 146 cursor.execute('''
147 -CREATE OR REPLACE VIEW ticket_collab_count_view AS  
148 -SELECT  
149 -COALESCE (t1.author, t2.author) as author,  
150 -(COALESCE(t1.count, 0) + COALESCE(t2.count, 0)) as count  
151 -FROM  
152 -(SELECT author, count(*) as count  
153 -FROM ticket_change  
154 -GROUP BY author  
155 -ORDER BY author  
156 -) AS t1  
157 -FULL OUTER JOIN  
158 -(SELECT reporter as author, count(*) as count  
159 -FROM ticket  
160 -GROUP BY reporter  
161 -ORDER BY reporter  
162 -) AS t2  
163 -ON t1.author = t2.author; 147 + CREATE OR REPLACE VIEW ticket_collab_count_view AS
  148 + SELECT
  149 + COALESCE (t1.author, t2.author) as author,
  150 + (COALESCE(t1.count, 0) + COALESCE(t2.count, 0)) as count
  151 + FROM
  152 + (SELECT author, count(*) as count
  153 + FROM ticket_change
  154 + GROUP BY author
  155 + ORDER BY author
  156 + ) AS t1
  157 + FULL OUTER JOIN
  158 + (SELECT reporter as author, count(*) as count
  159 + FROM ticket
  160 + GROUP BY reporter
  161 + ORDER BY reporter
  162 + ) AS t2
  163 + ON t1.author = t2.author;
164 164
165 -CREATE OR REPLACE VIEW wiki_collab_count_view AS  
166 -SELECT author, count(*) from wiki GROUP BY author;  
167 -''') 165 + CREATE OR REPLACE VIEW wiki_collab_count_view AS
  166 + SELECT author, count(*) from wiki GROUP BY author;
  167 + ''')
168 168
169 pass 169 pass
170 170
@@ -173,13 +173,15 @@ SELECT author, count(*) from wiki GROUP BY author; @@ -173,13 +173,15 @@ SELECT author, count(*) from wiki GROUP BY author;
173 173
174 cursor = connection.cursor() 174 cursor = connection.cursor()
175 cursor.execute(''' 175 cursor.execute('''
176 -DROP VIEW IF EXISTS revision_view;  
177 -DROP VIEW IF EXISTS ticket_view;  
178 -DROP VIEW IF EXISTS wiki_view;  
179 -''')  
180 - cursor.execute('DROP VIEW IF EXISTS attachment_view;') 176 + DROP VIEW IF EXISTS revision_view;
  177 + DROP VIEW IF EXISTS ticket_view;
  178 + DROP VIEW IF EXISTS wiki_view;
  179 + DROP VIEW IF EXISTS ticket_collab_count_view;
  180 + DROP VIEW IF EXISTS wiki_collab_count_view;
  181 + DROP VIEW IF EXISTS attachment_view;
  182 + ''')
181 183
182 - pass 184 + pass
183 185
184 models = { 186 models = {
185 u'proxy.attachment': { 187 u'proxy.attachment': {
@@ -245,4 +247,4 @@ DROP VIEW IF EXISTS wiki_view; @@ -245,4 +247,4 @@ DROP VIEW IF EXISTS wiki_view;
245 } 247 }
246 248
247 complete_apps = ['proxy'] 249 complete_apps = ['proxy']
248 - symmetrical = True 250 - symmetrical = True
  251 + symmetrical = True
249 \ No newline at end of file 252 \ No newline at end of file
src/proxy/trac/models.py
@@ -1,178 +0,0 @@ @@ -1,178 +0,0 @@
1 -# -*- coding: utf-8 -*-  
2 -  
3 -import os  
4 -import urllib2  
5 -  
6 -from django.conf import settings  
7 -from django.db import models, connections  
8 -from django.db.models.signals import post_save  
9 -from django.dispatch import receiver  
10 -  
11 -from accounts.models import User  
12 -from hitcounter.models import HitCounterModelMixin  
13 -  
14 -  
15 -class Attachment(models.Model, HitCounterModelMixin):  
16 - url = models.TextField(primary_key=True)  
17 - attach_id = models.TextField()  
18 - used_by = models.TextField()  
19 - filename = models.TextField()  
20 - author = models.TextField(blank=True)  
21 - description = models.TextField(blank=True)  
22 - created = models.DateTimeField(blank=True)  
23 - mimetype = models.TextField(blank=True)  
24 - size = models.IntegerField(blank=True)  
25 -  
26 - class Meta:  
27 - managed = False  
28 - db_table = 'attachment_view'  
29 -  
30 - @property  
31 - def filepath(self):  
32 - return os.path.join(  
33 - settings.ATTACHMENTS_FOLDER_PATH,  
34 - self.used_by,  
35 - self.attach_id,  
36 - urllib2.quote(self.filename.encode('utf8'))  
37 - )  
38 -  
39 - def get_absolute_url(self):  
40 - return u'/raw-attachment/{}'.format(self.url)  
41 -  
42 - def get_author(self):  
43 - try:  
44 - return User.objects.get(username=self.author)  
45 - except User.DoesNotExist:  
46 - return None  
47 -  
48 -  
49 -class Revision(models.Model, HitCounterModelMixin):  
50 - key = models.TextField(blank=True, primary_key=True)  
51 - rev = models.TextField(blank=True)  
52 - author = models.TextField(blank=True)  
53 - message = models.TextField(blank=True)  
54 - repository_name = models.TextField(blank=True)  
55 - created = models.DateTimeField(blank=True, null=True)  
56 -  
57 - class Meta:  
58 - managed = False  
59 - db_table = 'revision_view'  
60 -  
61 - def get_absolute_url(self):  
62 - return u'/changeset/{}/{}'.format(self.rev, self.repository_name)  
63 -  
64 - def get_author(self):  
65 - try:  
66 - return User.objects.get(username=self.author)  
67 - except User.DoesNotExist:  
68 - return None  
69 -  
70 -class Ticket(models.Model, HitCounterModelMixin):  
71 - id = models.IntegerField(primary_key=True)  
72 - summary = models.TextField(blank=True)  
73 - description = models.TextField(blank=True)  
74 - milestone = models.TextField(blank=True)  
75 - priority = models.TextField(blank=True)  
76 - component = models.TextField(blank=True)  
77 - version = models.TextField(blank=True)  
78 - severity = models.TextField(blank=True)  
79 - reporter = models.TextField(blank=True)  
80 - author = models.TextField(blank=True)  
81 - status = models.TextField(blank=True)  
82 - keywords = models.TextField(blank=True)  
83 - collaborators = models.TextField(blank=True)  
84 - created = models.DateTimeField(blank=True, null=True)  
85 - modified = models.DateTimeField(blank=True, null=True)  
86 - modified_by = models.TextField(blank=True)  
87 -  
88 - class Meta:  
89 - managed = False  
90 - db_table = 'ticket_view'  
91 -  
92 - def get_absolute_url(self):  
93 - return u'/ticket/{}'.format(self.id)  
94 -  
95 - def get_author(self):  
96 - try:  
97 - return User.objects.get(username=self.author)  
98 - except User.DoesNotExist:  
99 - return None  
100 -  
101 - def get_modified_by(self):  
102 - try:  
103 - return User.objects.get(username=self.modified_by)  
104 - except User.DoesNotExist:  
105 - return None  
106 -  
107 -class Wiki(models.Model, HitCounterModelMixin):  
108 - name = models.TextField(primary_key=True)  
109 - wiki_text = models.TextField(blank=True)  
110 - author = models.TextField(blank=True)  
111 - collaborators = models.TextField(blank=True)  
112 - created = models.DateTimeField(blank=True, null=True)  
113 - modified = models.DateTimeField(blank=True, null=True)  
114 - modified_by = models.TextField(blank=True)  
115 -  
116 - class Meta:  
117 - managed = False  
118 - db_table = 'wiki_view'  
119 -  
120 - def get_absolute_url(self):  
121 - return u'/wiki/{}'.format(self.name)  
122 -  
123 - def get_author(self):  
124 - try:  
125 - return User.objects.get(username=self.author)  
126 - except User.DoesNotExist:  
127 - return None  
128 -  
129 - def get_modified_by(self):  
130 - try:  
131 - return User.objects.get(username=self.modified_by)  
132 - except User.DoesNotExist:  
133 - return None  
134 -  
135 -  
136 -class WikiCollabCount(models.Model):  
137 - author = models.TextField(primary_key=True)  
138 - count = models.IntegerField()  
139 -  
140 - class Meta:  
141 - managed = False  
142 - db_table = 'wiki_collab_count_view'  
143 -  
144 -  
145 -class TicketCollabCount(models.Model):  
146 - author = models.TextField(primary_key=True)  
147 - count = models.IntegerField()  
148 -  
149 - class Meta:  
150 - managed = False  
151 - db_table = 'ticket_collab_count_view'  
152 -  
153 -  
154 -@receiver(post_save, sender=User)  
155 -def change_session_attribute_email(sender, instance, **kwargs):  
156 - cursor = connections['trac'].cursor()  
157 -  
158 - cursor.execute(("UPDATE session_attribute SET value=%s "  
159 - "WHERE name='email' AND sid=%s"),  
160 - [instance.email, instance.username])  
161 - cursor.execute(("UPDATE session_attribute SET value=%s "  
162 - "WHERE name='name' AND sid=%s"),  
163 - [instance.get_full_name(), instance.username])  
164 -  
165 - cursor.execute(("INSERT INTO session_attribute "  
166 - "(sid, authenticated, name, value) "  
167 - "SELECT %s, '1', 'email', %s WHERE NOT EXISTS "  
168 - "(SELECT 1 FROM session_attribute WHERE sid=%s "  
169 - "AND name='email')"),  
170 - [instance.username, instance.email, instance.username])  
171 -  
172 - cursor.execute(("INSERT INTO session_attribute "  
173 - "(sid, authenticated, name, value) "  
174 - "SELECT %s, '1', 'name', %s WHERE NOT EXISTS "  
175 - "(SELECT 1 FROM session_attribute WHERE sid=%s "  
176 - "AND name='name')"),  
177 - [instance.username, instance.get_full_name(),  
178 - instance.username])  
src/proxy/views.py
@@ -4,7 +4,7 @@ import os @@ -4,7 +4,7 @@ import os
4 from django.conf import settings 4 from django.conf import settings
5 5
6 from revproxy.views import ProxyView 6 from revproxy.views import ProxyView
7 -from trac.models import Wiki, Ticket, Revision 7 +from .models import Wiki, Ticket, Revision
8 from hitcounter.views import HitCounterViewMixin 8 from hitcounter.views import HitCounterViewMixin
9 9
10 10
src/search/templates/search/includes/search_filters.html
@@ -111,30 +111,34 @@ @@ -111,30 +111,34 @@
111 <h4>{% trans "Types" %}</h4> 111 <h4>{% trans "Types" %}</h4>
112 112
113 <ul class="unstyled-list"> 113 <ul class="unstyled-list">
114 - <li>  
115 - <span class="glyphicon glyphicon-book"></span>  
116 - <a href="{% append_to_get type='wiki' %}">{% trans "Wiki" %}</a>  
117 - </li> 114 + {% is_trac_enable as is_trac %}
  115 +
  116 + {% if is_trac %}
  117 + <li>
  118 + <span class="glyphicon glyphicon-book"></span>
  119 + <a href="{% append_to_get type='wiki' %}">{% trans "Wiki" %}</a>
  120 + </li>
  121 + <li>
  122 + <span class="glyphicon glyphicon-tag"></span>
  123 + <a href="{% append_to_get type='ticket' %}">{% trans "Ticket" %}</a>
  124 + </li>
  125 + <li>
  126 + <span class="glyphicon glyphicon-align-right"></span>
  127 + <a href="{% append_to_get type='changeset' %}">{% trans "Changeset" %}</a>
  128 + </li>
  129 + <li>
  130 + <span class="glyphicon glyphicon-user"></span>
  131 + <a href="{% append_to_get type='user' %}">{% trans "User" %}</a>
  132 + </li>
  133 + <li>
  134 + <span class="glyphicon glyphicon-file"></span>
  135 + <a href="{% append_to_get type='attachment' %}">{% trans "Attachment" %}</a>
  136 + </li>
  137 + {% endif %}
118 <li> 138 <li>
119 <span class="glyphicon glyphicon-envelope"></span> 139 <span class="glyphicon glyphicon-envelope"></span>
120 <a href="{% append_to_get type='thread' %}">{% trans "Discussion" %}</a> 140 <a href="{% append_to_get type='thread' %}">{% trans "Discussion" %}</a>
121 </li> 141 </li>
122 - <li>  
123 - <span class="glyphicon glyphicon-tag"></span>  
124 - <a href="{% append_to_get type='ticket' %}">{% trans "Ticket" %}</a>  
125 - </li>  
126 - <li>  
127 - <span class="glyphicon glyphicon-align-right"></span>  
128 - <a href="{% append_to_get type='changeset' %}">{% trans "Changeset" %}</a>  
129 - </li>  
130 - <li>  
131 - <span class="glyphicon glyphicon-user"></span>  
132 - <a href="{% append_to_get type='user' %}">{% trans "User" %}</a>  
133 - </li>  
134 - <li>  
135 - <span class="glyphicon glyphicon-file"></span>  
136 - <a href="{% append_to_get type='attachment' %}">{% trans "Attachment" %}</a>  
137 - </li>  
138 </ul> 142 </ul>
139 {% endif %} 143 {% endif %}
140 <hr /> 144 <hr />
src/search/views.py
@@ -5,7 +5,7 @@ from django.utils.translation import ugettext as _ @@ -5,7 +5,7 @@ from django.utils.translation import ugettext as _
5 5
6 from haystack.views import SearchView 6 from haystack.views import SearchView
7 7
8 -from proxy.trac.models import Attachment 8 +from proxy.models import Attachment
9 9
10 10
11 class ColabSearchView(SearchView): 11 class ColabSearchView(SearchView):
@@ -16,17 +16,6 @@ class ColabSearchView(SearchView): @@ -16,17 +16,6 @@ class ColabSearchView(SearchView):
16 ) 16 )
17 17
18 types = { 18 types = {
19 - 'wiki': {  
20 - 'name': _(u'Wiki'),  
21 - 'fields': (  
22 - ('author', _(u'Author'), self.request.GET.get('author')),  
23 - (  
24 - 'collaborators',  
25 - _(u'Collaborators'),  
26 - self.request.GET.get('collaborators'),  
27 - ),  
28 - ),  
29 - },  
30 'thread': { 19 'thread': {
31 'name': _(u'Discussion'), 20 'name': _(u'Discussion'),
32 'fields': ( 21 'fields': (
@@ -38,7 +27,22 @@ class ColabSearchView(SearchView): @@ -38,7 +27,22 @@ class ColabSearchView(SearchView):
38 ), 27 ),
39 ), 28 ),
40 }, 29 },
41 - 'ticket': { 30 + }
  31 +
  32 + if settings.TRAC_ENABLED:
  33 + types['wiki'] = {
  34 + 'name': _(u'Wiki'),
  35 + 'fields': (
  36 + ('author', _(u'Author'), self.request.GET.get('author')),
  37 + (
  38 + 'collaborators',
  39 + _(u'Collaborators'),
  40 + self.request.GET.get('collaborators'),
  41 + ),
  42 + ),
  43 + }
  44 +
  45 + types['ticket'] = {
42 'name': _(u'Ticket'), 46 'name': _(u'Ticket'),
43 'fields': ( 47 'fields': (
44 ( 48 (
@@ -79,8 +83,9 @@ class ColabSearchView(SearchView): @@ -79,8 +83,9 @@ class ColabSearchView(SearchView):
79 self.request.GET.get('collaborators') 83 self.request.GET.get('collaborators')
80 ), 84 ),
81 ), 85 ),
82 - },  
83 - 'changeset': { 86 + }
  87 +
  88 + types['changeset'] = {
84 'name': _(u'Changeset'), 89 'name': _(u'Changeset'),
85 'fields': ( 90 'fields': (
86 ('author', _(u'Author'), self.request.GET.get('author')), 91 ('author', _(u'Author'), self.request.GET.get('author')),
@@ -90,8 +95,9 @@ class ColabSearchView(SearchView): @@ -90,8 +95,9 @@ class ColabSearchView(SearchView):
90 self.request.GET.get('repository_name'), 95 self.request.GET.get('repository_name'),
91 ), 96 ),
92 ) 97 )
93 - },  
94 - 'user': { 98 + }
  99 +
  100 + types['user'] = {
95 'name': _(u'User'), 101 'name': _(u'User'),
96 'fields': ( 102 'fields': (
97 ( 103 (
@@ -107,8 +113,9 @@ class ColabSearchView(SearchView): @@ -107,8 +113,9 @@ class ColabSearchView(SearchView):
107 ), 113 ),
108 ('role', _(u'Role'), self.request.GET.get('role')) 114 ('role', _(u'Role'), self.request.GET.get('role'))
109 ), 115 ),
110 - },  
111 - 'attachment': { 116 + }
  117 +
  118 + types['attachment'] = {
112 'name': _(u'Attachment'), 119 'name': _(u'Attachment'),
113 'fields': ( 120 'fields': (
114 ( 121 (
@@ -128,7 +135,6 @@ class ColabSearchView(SearchView): @@ -128,7 +135,6 @@ class ColabSearchView(SearchView):
128 ('size', _(u'Size'), self.request.GET.get('size')), 135 ('size', _(u'Size'), self.request.GET.get('size')),
129 ) 136 )
130 } 137 }
131 - }  
132 138
133 try: 139 try:
134 type_chosen = self.form.cleaned_data.get('type') 140 type_chosen = self.form.cleaned_data.get('type')
src/super_archives/templatetags/superarchives.py
@@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
2 from django import template 2 from django import template
3 3
4 from super_archives.utils import url 4 from super_archives.utils import url
  5 +from django.conf import settings
5 6
6 7
7 register = template.Library() 8 register = template.Library()
@@ -32,3 +33,7 @@ def pop_from_get(context, **kwargs): @@ -32,3 +33,7 @@ def pop_from_get(context, **kwargs):
32 context['request'].META['QUERY_STRING'], 33 context['request'].META['QUERY_STRING'],
33 **kwargs 34 **kwargs
34 ) 35 )
  36 +
  37 +@register.assignment_tag
  38 +def is_trac_enable():
  39 + return settings.TRAC_ENABLED
35 \ No newline at end of file 40 \ No newline at end of file