Commit 500a12404773523d3837ad883504b4e3a2ea4fa0

Authored by Sergio Oliveira
2 parents 75292867 a3acbdfd

Merge pull request #18 from colab-community/update_trac_puppet

Remove trac dependency
src/colab/custom_settings.py
@@ -255,15 +255,6 @@ MESSAGE_TAGS = { @@ -255,15 +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 -  
266 -  
267 ### Feedzilla (planet) 258 ### Feedzilla (planet)
268 from feedzilla.settings import * 259 from feedzilla.settings import *
269 FEEDZILLA_PAGE_SIZE = 5 260 FEEDZILLA_PAGE_SIZE = 5
@@ -318,7 +309,16 @@ DPASTE_EXPIRE_DEFAULT = DPASTE_EXPIRE_CHOICES[4][0] @@ -318,7 +309,16 @@ DPASTE_EXPIRE_DEFAULT = DPASTE_EXPIRE_CHOICES[4][0]
318 DPASTE_DEFAULT_GIST_DESCRIPTION = 'Gist created on Colab Interlegis' 309 DPASTE_DEFAULT_GIST_DESCRIPTION = 'Gist created on Colab Interlegis'
319 DPASTE_DEFAULT_GIST_NAME = 'colab_paste' 310 DPASTE_DEFAULT_GIST_NAME = 'colab_paste'
320 311
  312 +
  313 +### Trac
  314 +TRAC_ENABLED = False
  315 +
321 try: 316 try:
322 from local_settings import * 317 from local_settings import *
323 except ImportError: 318 except ImportError:
324 pass 319 pass
  320 +
  321 +if TRAC_ENABLED:
  322 + INSTALLED_APPS = INSTALLED_APPS + (
  323 + 'proxy.trac',
  324 + )
325 \ No newline at end of file 325 \ No newline at end of file
src/colab/local_settings-dev.py
@@ -27,16 +27,23 @@ CONVERSEJS_BOSH_SERVICE_URL = 'http://localhost:5280/http-bind' @@ -27,16 +27,23 @@ CONVERSEJS_BOSH_SERVICE_URL = 'http://localhost:5280/http-bind'
27 27
28 DATABASES['default']['PASSWORD'] = 'colab' 28 DATABASES['default']['PASSWORD'] = 'colab'
29 DATABASES['default']['HOST'] = 'localhost' 29 DATABASES['default']['HOST'] = 'localhost'
  30 +
  31 +TRAC_ENABLED = False
  32 +
30 if TRAC_ENABLED: 33 if TRAC_ENABLED:
  34 + from trac_settings import *
  35 + DATABASES['trac'] = TRAC_DATABASE
31 DATABASES['trac']['PASSWORD'] = 'colab' 36 DATABASES['trac']['PASSWORD'] = 'colab'
32 DATABASES['trac']['HOST'] = 'localhost' 37 DATABASES['trac']['HOST'] = 'localhost'
33 38
34 HAYSTACK_CONNECTIONS['default']['URL'] = 'http://localhost:8983/solr/' 39 HAYSTACK_CONNECTIONS['default']['URL'] = 'http://localhost:8983/solr/'
35 40
  41 +COLAB_TRAC_URL = 'http://localhost:5000/trac/'
36 COLAB_CI_URL = 'http://localhost:8080/ci/' 42 COLAB_CI_URL = 'http://localhost:8080/ci/'
37 COLAB_GITLAB_URL = 'http://localhost:8090/gitlab/' 43 COLAB_GITLAB_URL = 'http://localhost:8090/gitlab/'
38 COLAB_REDMINE_URL = 'http://localhost:9080/redmine/' 44 COLAB_REDMINE_URL = 'http://localhost:9080/redmine/'
39 45
  46 +
40 CONVERSEJS_ENABLED = False 47 CONVERSEJS_ENABLED = False
41 48
42 DIAZO_THEME = SITE_URL 49 DIAZO_THEME = SITE_URL
src/home/views.py
@@ -23,18 +23,24 @@ def index(request): @@ -23,18 +23,24 @@ 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()  
30 -  
31 - count_types['ticket'] = sum([  
32 - ticket.count for ticket in TicketCollabCount.objects.all()  
33 - ])  
34 -  
35 - count_types['wiki'] = sum([  
36 - wiki.count for wiki in WikiCollabCount.objects.all()  
37 - ]) 26 + count_types['thread'] = SearchQuerySet().filter(
  27 + type='thread',
  28 + ).count()
  29 + # TODO: this section should be inside trac app and only use it here
  30 + if settings.TRAC_ENABLED:
  31 + for type in ['changeset', 'attachment']:
  32 + count_types[type] = SearchQuerySet().filter(
  33 + type=type,
  34 + ).count()
  35 +
  36 + count_types['ticket'] = sum([
  37 + ticket.count for ticket in TicketCollabCount.objects.all()
  38 + ])
  39 +
  40 + count_types['wiki'] = sum([
  41 + wiki.count for wiki in WikiCollabCount.objects.all()
  42 + ])
  43 +
38 cache.set('home_chart', count_types) 44 cache.set('home_chart', count_types)
39 45
40 for key in count_types.keys(): 46 for key in count_types.keys():
src/proxy/migrations/0001_initial.py
@@ -1,248 +0,0 @@ @@ -1,248 +0,0 @@
1 -# -*- coding: utf-8 -*-  
2 -import datetime  
3 -from django.db import connections  
4 -from south.db import db  
5 -from south.v2 import SchemaMigration  
6 -from django.db import models  
7 -  
8 -  
9 -class Migration(SchemaMigration):  
10 -  
11 - def forwards(self, orm):  
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' + (MAX(wiki.time)/1000000) * INTERVAL '1s' AS created,  
24 - TIMESTAMP WITH TIME ZONE 'epoch' + (MIN(wiki.time)/1000000) * INTERVAL '1s' AS modified  
25 - FROM wiki  
26 - GROUP BY wiki.name;  
27 -  
28 - CREATE OR REPLACE VIEW ticket_view AS SELECT  
29 - ticket.id AS id,  
30 - ticket.summary as summary,  
31 - ticket.description as description,  
32 - ticket.milestone as milestone,  
33 - ticket.priority as priority,  
34 - ticket.component as component,  
35 - ticket.version as version,  
36 - ticket.severity as severity,  
37 - ticket.reporter as reporter,  
38 - ticket.reporter as author,  
39 - ticket.status as status,  
40 - ticket.keywords as keywords,  
41 - (SELECT  
42 - string_agg(DISTINCT ticket_change.author, ', ')  
43 - FROM ticket_change WHERE ticket_change.ticket = ticket.id  
44 - GROUP BY ticket_change.ticket) as collaborators,  
45 - TIMESTAMP WITH TIME ZONE 'epoch' + (time/1000000)* INTERVAL '1s' AS created,  
46 - TIMESTAMP WITH TIME ZONE 'epoch' + (changetime/1000000) * INTERVAL '1s' AS modified  
47 - FROM ticket;  
48 -  
49 - CREATE OR REPLACE VIEW revision_view AS SELECT  
50 - revision.rev,  
51 - revision.author,  
52 - revision.message,  
53 - repository.value AS repository_name,  
54 - TIMESTAMP WITH TIME ZONE 'epoch' + (revision.time/1000000) * INTERVAL '1s' AS created  
55 - FROM revision  
56 - INNER JOIN repository ON(  
57 - repository.id = revision.repos  
58 - AND repository.name = 'name'  
59 - AND repository.value != ''  
60 - );  
61 - ''')  
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 -''')  
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 -''')  
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 -''')  
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;  
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 -''')  
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;  
164 -  
165 -CREATE OR REPLACE VIEW wiki_collab_count_view AS  
166 -SELECT author, count(*) from wiki GROUP BY author;  
167 -''')  
168 -  
169 - pass  
170 -  
171 - def backwards(self, orm):  
172 - connection = connections['trac']  
173 -  
174 - cursor = connection.cursor()  
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;')  
181 -  
182 - pass  
183 -  
184 - models = {  
185 - u'proxy.attachment': {  
186 - 'Meta': {'object_name': 'Attachment', 'db_table': "'attachment_view'", 'managed': 'False'},  
187 - 'attach_id': ('django.db.models.fields.TextField', [], {}),  
188 - 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}),  
189 - 'created': ('django.db.models.fields.DateTimeField', [], {'blank': 'True'}),  
190 - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),  
191 - 'filename': ('django.db.models.fields.TextField', [], {}),  
192 - 'mimetype': ('django.db.models.fields.TextField', [], {'blank': 'True'}),  
193 - 'size': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),  
194 - 'url': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}),  
195 - 'used_by': ('django.db.models.fields.TextField', [], {})  
196 - },  
197 - u'proxy.revision': {  
198 - 'Meta': {'object_name': 'Revision', 'db_table': "'revision_view'", 'managed': 'False'},  
199 - 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}),  
200 - 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),  
201 - 'key': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}),  
202 - 'message': ('django.db.models.fields.TextField', [], {'blank': 'True'}),  
203 - 'repository_name': ('django.db.models.fields.TextField', [], {'blank': 'True'}),  
204 - 'rev': ('django.db.models.fields.TextField', [], {'blank': 'True'})  
205 - },  
206 - u'proxy.ticket': {  
207 - 'Meta': {'object_name': 'Ticket', 'db_table': "'ticket_view'", 'managed': 'False'},  
208 - 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}),  
209 - 'collaborators': ('django.db.models.fields.TextField', [], {'blank': 'True'}),  
210 - 'component': ('django.db.models.fields.TextField', [], {'blank': 'True'}),  
211 - 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),  
212 - 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),  
213 - 'id': ('django.db.models.fields.IntegerField', [], {'primary_key': 'True'}),  
214 - 'keywords': ('django.db.models.fields.TextField', [], {'blank': 'True'}),  
215 - 'milestone': ('django.db.models.fields.TextField', [], {'blank': 'True'}),  
216 - 'modified': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),  
217 - 'modified_by': ('django.db.models.fields.TextField', [], {'blank': 'True'}),  
218 - 'priority': ('django.db.models.fields.TextField', [], {'blank': 'True'}),  
219 - 'reporter': ('django.db.models.fields.TextField', [], {'blank': 'True'}),  
220 - 'severity': ('django.db.models.fields.TextField', [], {'blank': 'True'}),  
221 - 'status': ('django.db.models.fields.TextField', [], {'blank': 'True'}),  
222 - 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),  
223 - 'version': ('django.db.models.fields.TextField', [], {'blank': 'True'})  
224 - },  
225 - u'proxy.ticketcollabcount': {  
226 - 'Meta': {'object_name': 'TicketCollabCount', 'db_table': "'ticket_collab_count_view'", 'managed': 'False'},  
227 - 'author': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}),  
228 - 'count': ('django.db.models.fields.IntegerField', [], {})  
229 - },  
230 - u'proxy.wiki': {  
231 - 'Meta': {'object_name': 'Wiki', 'db_table': "'wiki_view'", 'managed': 'False'},  
232 - 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}),  
233 - 'collaborators': ('django.db.models.fields.TextField', [], {'blank': 'True'}),  
234 - 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),  
235 - 'modified': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),  
236 - 'modified_by': ('django.db.models.fields.TextField', [], {'blank': 'True'}),  
237 - 'name': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}),  
238 - 'wiki_text': ('django.db.models.fields.TextField', [], {'blank': 'True'})  
239 - },  
240 - u'proxy.wikicollabcount': {  
241 - 'Meta': {'object_name': 'WikiCollabCount', 'db_table': "'wiki_collab_count_view'", 'managed': 'False'},  
242 - 'author': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}),  
243 - 'count': ('django.db.models.fields.IntegerField', [], {})  
244 - }  
245 - }  
246 -  
247 - complete_apps = ['proxy']  
248 - symmetrical = True  
src/proxy/migrations/__init__.py
src/proxy/models.py
1 # -*- coding: utf-8 -*- 1 # -*- coding: utf-8 -*-
2 - 2 +from django.db import models
  3 +from django.conf import settings
3 import os 4 import os
4 import urllib2 5 import urllib2
5 6
@@ -11,7 +12,6 @@ from django.dispatch import receiver @@ -11,7 +12,6 @@ from django.dispatch import receiver
11 from accounts.models import User 12 from accounts.models import User
12 from hitcounter.models import HitCounterModelMixin 13 from hitcounter.models import HitCounterModelMixin
13 14
14 -  
15 class Attachment(models.Model, HitCounterModelMixin): 15 class Attachment(models.Model, HitCounterModelMixin):
16 url = models.TextField(primary_key=True) 16 url = models.TextField(primary_key=True)
17 attach_id = models.TextField() 17 attach_id = models.TextField()
@@ -104,7 +104,6 @@ class Ticket(models.Model, HitCounterModelMixin): @@ -104,7 +104,6 @@ class Ticket(models.Model, HitCounterModelMixin):
104 except User.DoesNotExist: 104 except User.DoesNotExist:
105 return None 105 return None
106 106
107 -  
108 class Wiki(models.Model, HitCounterModelMixin): 107 class Wiki(models.Model, HitCounterModelMixin):
109 name = models.TextField(primary_key=True) 108 name = models.TextField(primary_key=True)
110 wiki_text = models.TextField(blank=True) 109 wiki_text = models.TextField(blank=True)
src/proxy/templatetags/__init__.py 0 → 100644
src/proxy/templatetags/proxy.py 0 → 100644
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +from django import template
  2 +
  3 +from super_archives.utils import url
  4 +from django.conf import settings
  5 +
  6 +
  7 +register = template.Library()
  8 +TEMPLATE_PATH = 'proxy/tags/'
  9 +
  10 +@register.assignment_tag
  11 +def is_trac_enable():
  12 + return settings.TRAC_ENABLED
0 \ No newline at end of file 13 \ No newline at end of file
src/proxy/trac/__init__.py 0 → 100644
src/proxy/trac/admin.py 0 → 100644
@@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
  1 +from django.contrib import admin
  2 +
  3 +# Register your models here.
src/proxy/trac/migrations/0001_initial.py 0 → 100644
@@ -0,0 +1,250 @@ @@ -0,0 +1,250 @@
  1 +# -*- coding: utf-8 -*-
  2 +import datetime
  3 +from django.db import connections
  4 +from south.db import db
  5 +from south.v2 import SchemaMigration
  6 +from django.db import models
  7 +
  8 +
  9 +class Migration(SchemaMigration):
  10 +
  11 + def forwards(self, orm):
  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' + (MAX(wiki.time)/1000000) * INTERVAL '1s' AS created,
  24 + TIMESTAMP WITH TIME ZONE 'epoch' + (MIN(wiki.time)/1000000) * INTERVAL '1s' AS modified
  25 + FROM wiki
  26 + GROUP BY wiki.name;
  27 +
  28 + CREATE OR REPLACE VIEW ticket_view AS SELECT
  29 + ticket.id AS id,
  30 + ticket.summary as summary,
  31 + ticket.description as description,
  32 + ticket.milestone as milestone,
  33 + ticket.priority as priority,
  34 + ticket.component as component,
  35 + ticket.version as version,
  36 + ticket.severity as severity,
  37 + ticket.reporter as reporter,
  38 + ticket.reporter as author,
  39 + ticket.status as status,
  40 + ticket.keywords as keywords,
  41 + (SELECT
  42 + string_agg(DISTINCT ticket_change.author, ', ')
  43 + FROM ticket_change WHERE ticket_change.ticket = ticket.id
  44 + GROUP BY ticket_change.ticket) as collaborators,
  45 + TIMESTAMP WITH TIME ZONE 'epoch' + (time/1000000)* INTERVAL '1s' AS created,
  46 + TIMESTAMP WITH TIME ZONE 'epoch' + (changetime/1000000) * INTERVAL '1s' AS modified
  47 + FROM ticket;
  48 +
  49 + CREATE OR REPLACE VIEW revision_view AS SELECT
  50 + revision.rev,
  51 + revision.author,
  52 + revision.message,
  53 + repository.value AS repository_name,
  54 + TIMESTAMP WITH TIME ZONE 'epoch' + (revision.time/1000000) * INTERVAL '1s' AS created
  55 + FROM revision
  56 + INNER JOIN repository ON(
  57 + repository.id = revision.repos
  58 + AND repository.name = 'name'
  59 + AND repository.value != ''
  60 + );
  61 + ''')
  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 + ''')
  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 + ''')
  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 + ''')
  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;
  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 + ''')
  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;
  164 +
  165 + CREATE OR REPLACE VIEW wiki_collab_count_view AS
  166 + SELECT author, count(*) from wiki GROUP BY author;
  167 + ''')
  168 +
  169 + pass
  170 +
  171 + def backwards(self, orm):
  172 + connection = connections['trac']
  173 +
  174 + cursor = connection.cursor()
  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 + 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 + ''')
  183 +
  184 + pass
  185 +
  186 + models = {
  187 + u'proxy.attachment': {
  188 + 'Meta': {'object_name': 'Attachment', 'db_table': "'attachment_view'", 'managed': 'False'},
  189 + 'attach_id': ('django.db.models.fields.TextField', [], {}),
  190 + 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  191 + 'created': ('django.db.models.fields.DateTimeField', [], {'blank': 'True'}),
  192 + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  193 + 'filename': ('django.db.models.fields.TextField', [], {}),
  194 + 'mimetype': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  195 + 'size': ('django.db.models.fields.IntegerField', [], {'blank': 'True'}),
  196 + 'url': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}),
  197 + 'used_by': ('django.db.models.fields.TextField', [], {})
  198 + },
  199 + u'proxy.revision': {
  200 + 'Meta': {'object_name': 'Revision', 'db_table': "'revision_view'", 'managed': 'False'},
  201 + 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  202 + 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
  203 + 'key': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}),
  204 + 'message': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  205 + 'repository_name': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  206 + 'rev': ('django.db.models.fields.TextField', [], {'blank': 'True'})
  207 + },
  208 + u'proxy.ticket': {
  209 + 'Meta': {'object_name': 'Ticket', 'db_table': "'ticket_view'", 'managed': 'False'},
  210 + 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  211 + 'collaborators': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  212 + 'component': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  213 + 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
  214 + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  215 + 'id': ('django.db.models.fields.IntegerField', [], {'primary_key': 'True'}),
  216 + 'keywords': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  217 + 'milestone': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  218 + 'modified': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
  219 + 'modified_by': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  220 + 'priority': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  221 + 'reporter': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  222 + 'severity': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  223 + 'status': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  224 + 'summary': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  225 + 'version': ('django.db.models.fields.TextField', [], {'blank': 'True'})
  226 + },
  227 + u'proxy.ticketcollabcount': {
  228 + 'Meta': {'object_name': 'TicketCollabCount', 'db_table': "'ticket_collab_count_view'", 'managed': 'False'},
  229 + 'author': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}),
  230 + 'count': ('django.db.models.fields.IntegerField', [], {})
  231 + },
  232 + u'proxy.wiki': {
  233 + 'Meta': {'object_name': 'Wiki', 'db_table': "'wiki_view'", 'managed': 'False'},
  234 + 'author': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  235 + 'collaborators': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  236 + 'created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
  237 + 'modified': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}),
  238 + 'modified_by': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
  239 + 'name': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}),
  240 + 'wiki_text': ('django.db.models.fields.TextField', [], {'blank': 'True'})
  241 + },
  242 + u'proxy.wikicollabcount': {
  243 + 'Meta': {'object_name': 'WikiCollabCount', 'db_table': "'wiki_collab_count_view'", 'managed': 'False'},
  244 + 'author': ('django.db.models.fields.TextField', [], {'primary_key': 'True'}),
  245 + 'count': ('django.db.models.fields.IntegerField', [], {})
  246 + }
  247 + }
  248 +
  249 + complete_apps = ['proxy']
  250 + symmetrical = True
0 \ No newline at end of file 251 \ No newline at end of file
src/proxy/trac/migrations/__init__.py 0 → 100644
src/proxy/trac/models.py 0 → 100644
src/proxy/trac/tests.py 0 → 100644
@@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
  1 +from django.test import TestCase
  2 +
  3 +# Create your tests here.
src/proxy/trac/views.py 0 → 100644
@@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
  1 +from django.shortcuts import render
  2 +
  3 +# Create your views here.
src/search/templates/search/includes/search_filters.html
1 -{% load i18n superarchives %} 1 +{% load i18n superarchives proxy %}
2 2
3 {% if filters %} 3 {% if filters %}
4 <ul class="unstyled-list"> 4 <ul class="unstyled-list">
@@ -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
@@ -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 + # TODO: Replace for a more generic plugin architecture
  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()
@@ -31,4 +32,4 @@ def pop_from_get(context, **kwargs): @@ -31,4 +32,4 @@ def pop_from_get(context, **kwargs):
31 context['request'].META['PATH_INFO'], 32 context['request'].META['PATH_INFO'],
32 context['request'].META['QUERY_STRING'], 33 context['request'].META['QUERY_STRING'],
33 **kwargs 34 **kwargs
34 - ) 35 - )
  36 + )
35 \ No newline at end of file 37 \ No newline at end of file
src/templates/base.html
1 <!DOCTYPE html> 1 <!DOCTYPE html>
2 -{% load i18n browserid conversejs gravatar %} 2 +{% load i18n browserid conversejs gravatar proxy %}
  3 +
  4 +{% is_trac_enable as is_trac %}
  5 +
3 <html> 6 <html>
4 <head> 7 <head>
5 {% block head %} 8 {% block head %}
@@ -57,34 +60,42 @@ @@ -57,34 +60,42 @@
57 </button> 60 </button>
58 <a class="navbar-brand" href="/"><img alt="Colab" src="/static/img/logo_nav.png"></a> 61 <a class="navbar-brand" href="/"><img alt="Colab" src="/static/img/logo_nav.png"></a>
59 </div> 62 </div>
60 -  
61 <div class="collapse navbar-collapse navbar-main"> 63 <div class="collapse navbar-collapse navbar-main">
62 <ul class="nav navbar-nav"> 64 <ul class="nav navbar-nav">
63 - <li>  
64 - <a href="/timeline">{% trans "Timeline" %}</a></li>  
65 - </li> 65 +
  66 + {% if is_trac %}
  67 + <li>
  68 + <a href="/timeline">{% trans "Timeline" %}</a></li>
  69 + </li>
  70 + {% endif %}
  71 +
66 <li> 72 <li>
67 <a href="{% url 'thread_list' %}">{% trans "Groups" %}</a> 73 <a href="{% url 'thread_list' %}">{% trans "Groups" %}</a>
68 </li> 74 </li>
69 <li> 75 <li>
70 <a href="{% url "feedzilla_index" %}">{% trans "Blogs" %}</a> 76 <a href="{% url "feedzilla_index" %}">{% trans "Blogs" %}</a>
71 </li> 77 </li>
72 - <li class="dropdown">  
73 - <a href="#" class="dropdown-toggle" data-toggle="dropdown">{% trans "Contribute" %} <b class="caret"></b></a>  
74 - <ul class="dropdown-menu">  
75 - <li><a href="/wiki">Wiki</a></li>  
76 - {% if user.is_active %}  
77 - <li><a href="/wiki/WikiNewPage">{% trans "New Wiki Page" %}</a></li>  
78 - {% endif %}  
79 - <li><a href="/report">{% trans "View Tickets" %}</a></li>  
80 - {% if user.is_active %}  
81 - <li><a href="/newticket">{% trans "New Ticket" %}</a></li>  
82 - {% endif %}  
83 - <li><a href="/roadmap">{% trans "Roadmap" %}</a></li>  
84 - <li><a href="/browser">{% trans "Browse Source" %}</a></li>  
85 - <li><a href="/ci">{% trans "Continuous Integration" %}</a></li>  
86 - </ul>  
87 - </li> 78 +
  79 + {% if is_trac %}
  80 + <li class="dropdown">
  81 + <a href="#" class="dropdown-toggle" data-toggle="dropdown">{% trans "Contribute" %} <b class="caret"></b></a>
  82 + <ul class="dropdown-menu">
  83 + <li><a href="/wiki">Wiki</a></li>
  84 + {% if user.is_active %}
  85 + <li><a href="/wiki/WikiNewPage">{% trans "New Wiki Page" %}</a></li>
  86 + {% endif %}
  87 + <li><a href="/report">{% trans "View Tickets" %}</a></li>
  88 + {% if user.is_active %}
  89 + <li><a href="/newticket">{% trans "New Ticket" %}</a></li>
  90 + {% endif %}
  91 + <li><a href="/roadmap">{% trans "Roadmap" %}</a></li>
  92 + <li><a href="/browser">{% trans "Browse Source" %}</a></li>
  93 + <!-- TODO: Must be optional like trac and separated --!>
  94 + <li><a href="/ci">{% trans "Continuous Integration" %}</a></li>
  95 + </ul>
  96 + </li>
  97 + {% endif %}
  98 +
88 <li class="hidden-lg hidden-md"> 99 <li class="hidden-lg hidden-md">
89 <a href="{% url 'haystack_search' %}?q=">{% trans "Search" %}</a> 100 <a href="{% url 'haystack_search' %}?q=">{% trans "Search" %}</a>
90 </li> 101 </li>