Commit beb38b3b52b555759c4bbc4757e983e0113eafa0
1 parent
ca702a62
Exists in
master
and in
39 other branches
Fazendo merge com https://bitbucket.org/seocam/atu-colab/src/f70c46c4b63d
git-svn-id: http://repositorio.interlegis.gov.br/colab/trunk@6215 bee1b3ed-c3eb-0310-9994-b88e04532788
Showing
17 changed files
with
291 additions
and
19 deletions
Show diff stats
colab/api/handlers.py
@@ -7,6 +7,7 @@ from django.contrib.auth.decorators import login_required | @@ -7,6 +7,7 @@ from django.contrib.auth.decorators import login_required | ||
7 | from piston.utils import rc | 7 | from piston.utils import rc |
8 | from piston.handler import BaseHandler | 8 | from piston.handler import BaseHandler |
9 | 9 | ||
10 | +from colab import solrutils | ||
10 | from colab.super_archives.models import Message, PageHit | 11 | from colab.super_archives.models import Message, PageHit |
11 | 12 | ||
12 | 13 | ||
@@ -69,3 +70,34 @@ class CountHandler(BaseHandler): | @@ -69,3 +70,34 @@ class CountHandler(BaseHandler): | ||
69 | 70 | ||
70 | return rc.CREATED | 71 | return rc.CREATED |
71 | 72 | ||
73 | +class SearchHandler(BaseHandler): | ||
74 | + allowed_methods = ('GET', ) | ||
75 | + | ||
76 | + def read(self, request): | ||
77 | + query = request.GET.get('q') | ||
78 | + page = request.GET.get('p', 1) | ||
79 | + results_per_page = request.GET.get('n', 50) | ||
80 | + order = request.GET.get('o') | ||
81 | + | ||
82 | + if not query: | ||
83 | + return 'Query cannot be empty.' | ||
84 | + else: | ||
85 | + query = query.encode('utf-8') | ||
86 | + | ||
87 | + try: | ||
88 | + n = int(results_per_page) | ||
89 | + except ValueError: | ||
90 | + n = 10 | ||
91 | + | ||
92 | + if 1 > n > 500: | ||
93 | + n = 1 | ||
94 | + | ||
95 | + try: | ||
96 | + page = int(page) | ||
97 | + except ValueError: | ||
98 | + page = 1 | ||
99 | + | ||
100 | + if page < 1: | ||
101 | + page = 1 | ||
102 | + | ||
103 | + return solrutils.select(query, results_per_page, page, order) |
colab/api/urls.py
@@ -2,13 +2,15 @@ from django.conf.urls.defaults import patterns, include, url | @@ -2,13 +2,15 @@ from django.conf.urls.defaults import patterns, include, url | ||
2 | 2 | ||
3 | from piston.resource import Resource | 3 | from piston.resource import Resource |
4 | 4 | ||
5 | -from colab.api.handlers import VoteHandler, CountHandler | 5 | +from colab.api.handlers import VoteHandler, CountHandler, SearchHandler |
6 | 6 | ||
7 | 7 | ||
8 | vote_handler = Resource(VoteHandler) | 8 | vote_handler = Resource(VoteHandler) |
9 | count_handler = Resource(CountHandler) | 9 | count_handler = Resource(CountHandler) |
10 | +search_handler = Resource(SearchHandler) | ||
10 | 11 | ||
11 | urlpatterns = patterns('', | 12 | urlpatterns = patterns('', |
12 | url(r'message/(?P<message_id>\d+)/vote$', vote_handler), | 13 | url(r'message/(?P<message_id>\d+)/vote$', vote_handler), |
13 | url(r'hit/$', count_handler), | 14 | url(r'hit/$', count_handler), |
14 | -) | ||
15 | \ No newline at end of file | 15 | \ No newline at end of file |
16 | + url(r'search/$', search_handler), | ||
17 | +) |
colab/settings.py
@@ -153,7 +153,7 @@ SOLR_HOSTNAME = '10.1.2.154' | @@ -153,7 +153,7 @@ SOLR_HOSTNAME = '10.1.2.154' | ||
153 | SOLR_PORT = '8080' | 153 | SOLR_PORT = '8080' |
154 | SOLR_SELECT_PATH = '/solr/select' | 154 | SOLR_SELECT_PATH = '/solr/select' |
155 | 155 | ||
156 | -SOLR_COLAB_URI = 'http://colab.interlegis.gov.br' | 156 | +SOLR_COLAB_URI = 'http://colab.interlegis.leg.br' |
157 | SOLR_BASE_QUERY = """ | 157 | SOLR_BASE_QUERY = """ |
158 | ((Type:changeset OR Type:ticket OR Type:wiki OR Type:thread) AND Title:["" TO *]) | 158 | ((Type:changeset OR Type:ticket OR Type:wiki OR Type:thread) AND Title:["" TO *]) |
159 | """ | 159 | """ |
colab/settings_local-dev.py
@@ -14,11 +14,13 @@ DATABASES = { | @@ -14,11 +14,13 @@ DATABASES = { | ||
14 | } | 14 | } |
15 | } | 15 | } |
16 | 16 | ||
17 | +SOLR_COLAB_URI = None | ||
18 | + | ||
17 | # Make this unique, and don't share it with anybody. | 19 | # Make this unique, and don't share it with anybody. |
18 | SECRET_KEY = ')(jksdfhsjkadfhjkh234ns!8fqu-1186h$vuj' | 20 | SECRET_KEY = ')(jksdfhsjkadfhjkh234ns!8fqu-1186h$vuj' |
19 | 21 | ||
20 | -import socks | ||
21 | -SOCKS_TYPE = socks.PROXY_TYPE_SOCKS5 | ||
22 | -SOCKS_SERVER = '127.0.0.1' | ||
23 | -SOCKS_PORT = 9050 | 22 | +#import socks |
23 | +#SOCKS_TYPE = socks.PROXY_TYPE_SOCKS5 | ||
24 | +#SOCKS_SERVER = '127.0.0.1' | ||
25 | +#SOCKS_PORT = 9050 | ||
24 | 26 |
colab/solrutils.py
@@ -61,7 +61,7 @@ def get_document_url(doc): | @@ -61,7 +61,7 @@ def get_document_url(doc): | ||
61 | doc_type = doc.get('Type') | 61 | doc_type = doc.get('Type') |
62 | 62 | ||
63 | url = '' | 63 | url = '' |
64 | - if doc_type in ('ticket', 'wiki', 'changeset'): | 64 | + if settings.SOLR_COLAB_URI: |
65 | url += settings.SOLR_COLAB_URI | 65 | url += settings.SOLR_COLAB_URI |
66 | 66 | ||
67 | url += doc.get('path_string', '') | 67 | url += doc.get('path_string', '') |
296 Bytes
colab/super_archives/admin.py
@@ -3,7 +3,7 @@ from django.contrib import admin | @@ -3,7 +3,7 @@ from django.contrib import admin | ||
3 | from colab.super_archives.models import Message, Thread, UserProfile | 3 | from colab.super_archives.models import Message, Thread, UserProfile |
4 | 4 | ||
5 | class MessageAdmin(admin.ModelAdmin): | 5 | class MessageAdmin(admin.ModelAdmin): |
6 | - list_filter = ('spam', 'mailinglist', 'received_time', ) | 6 | + list_filter = ('spam', 'thread__mailinglist', 'received_time', ) |
7 | search_fields = ( | 7 | search_fields = ( |
8 | 'id', | 8 | 'id', |
9 | 'subject', | 9 | 'subject', |
colab/super_archives/management/commands/import_emails.py
@@ -130,14 +130,14 @@ class Command(BaseCommand, object): | @@ -130,14 +130,14 @@ class Command(BaseCommand, object): | ||
130 | for index, msg in self.parse_emails(mbox_path, n_msgs): | 130 | for index, msg in self.parse_emails(mbox_path, n_msgs): |
131 | yield mailinglist_name, msg, index | 131 | yield mailinglist_name, msg, index |
132 | 132 | ||
133 | - def get_thread(self, email): | 133 | + def get_thread(self, email, mailinglist): |
134 | """Group messages by thread looking for similar subjects""" | 134 | """Group messages by thread looking for similar subjects""" |
135 | 135 | ||
136 | subject_slug = slugify(email.subject_clean) | 136 | subject_slug = slugify(email.subject_clean) |
137 | thread = self.THREAD_CACHE.get(subject_slug) | 137 | thread = self.THREAD_CACHE.get(subject_slug) |
138 | if thread is None: | 138 | if thread is None: |
139 | thread = Thread.objects.get_or_create( | 139 | thread = Thread.objects.get_or_create( |
140 | - mailinglist=email.mailinglist, | 140 | + mailinglist=mailinglist, |
141 | subject_token=subject_slug | 141 | subject_token=subject_slug |
142 | )[0] | 142 | )[0] |
143 | 143 | ||
@@ -156,7 +156,10 @@ class Command(BaseCommand, object): | @@ -156,7 +156,10 @@ class Command(BaseCommand, object): | ||
156 | 156 | ||
157 | try: | 157 | try: |
158 | # If the message is already at the database don't do anything | 158 | # If the message is already at the database don't do anything |
159 | - Message.objects.get(message_id=email_msg.get('Message-ID')) | 159 | + message = Message.objects.get( |
160 | + message_id=email_msg.get('Message-ID')) | ||
161 | + if message.thread.mailinglist.name != mailinglist.name: | ||
162 | + raise ObjectDoesNotExist | ||
160 | except ObjectDoesNotExist: | 163 | except ObjectDoesNotExist: |
161 | self.create_email(mailinglist, email_msg) | 164 | self.create_email(mailinglist, email_msg) |
162 | 165 | ||
@@ -181,13 +184,12 @@ class Command(BaseCommand, object): | @@ -181,13 +184,12 @@ class Command(BaseCommand, object): | ||
181 | email = Message.objects.create( | 184 | email = Message.objects.create( |
182 | message_id=email_msg.get('Message-ID'), | 185 | message_id=email_msg.get('Message-ID'), |
183 | from_address=email_addr, | 186 | from_address=email_addr, |
184 | - mailinglist=mailinglist, | ||
185 | subject=subject, | 187 | subject=subject, |
186 | subject_clean=self.RE_SUBJECT_CLEAN.sub('', subject).strip(), | 188 | subject_clean=self.RE_SUBJECT_CLEAN.sub('', subject).strip(), |
187 | body=email_msg.get_body(), | 189 | body=email_msg.get_body(), |
188 | received_time=email_msg.get_received_datetime(), | 190 | received_time=email_msg.get_received_datetime(), |
189 | ) | 191 | ) |
190 | - email.thread = self.get_thread(email) | 192 | + email.thread = self.get_thread(email, mailinglist) |
191 | email.save() | 193 | email.save() |
192 | 194 | ||
193 | @transaction.commit_manually | 195 | @transaction.commit_manually |
@@ -245,4 +247,4 @@ class Command(BaseCommand, object): | @@ -245,4 +247,4 @@ class Command(BaseCommand, object): | ||
245 | options.get('all'), options.get('exclude_lists')) | 247 | options.get('all'), options.get('exclude_lists')) |
246 | 248 | ||
247 | os.remove(lock_file) | 249 | os.remove(lock_file) |
248 | - | ||
249 | \ No newline at end of file | 250 | \ No newline at end of file |
251 | + |
colab/super_archives/migrations/0009_auto__del_field_message_mailinglist.py
0 → 100644
@@ -0,0 +1,136 @@ | @@ -0,0 +1,136 @@ | ||
1 | +# encoding: utf-8 | ||
2 | +import datetime | ||
3 | +from south.db import db | ||
4 | +from south.v2 import SchemaMigration | ||
5 | +from django.db import models | ||
6 | + | ||
7 | +class Migration(SchemaMigration): | ||
8 | + | ||
9 | + def forwards(self, orm): | ||
10 | + | ||
11 | + # Deleting field 'Message.mailinglist' | ||
12 | + db.delete_column('super_archives_message', 'mailinglist_id') | ||
13 | + | ||
14 | + | ||
15 | + def backwards(self, orm): | ||
16 | + | ||
17 | + # User chose to not deal with backwards NULL issues for 'Message.mailinglist' | ||
18 | + raise RuntimeError("Cannot reverse this migration. 'Message.mailinglist' and its values cannot be restored.") | ||
19 | + | ||
20 | + | ||
21 | + models = { | ||
22 | + 'auth.group': { | ||
23 | + 'Meta': {'object_name': 'Group'}, | ||
24 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
25 | + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), | ||
26 | + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) | ||
27 | + }, | ||
28 | + 'auth.permission': { | ||
29 | + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, | ||
30 | + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
31 | + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), | ||
32 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
33 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) | ||
34 | + }, | ||
35 | + 'auth.user': { | ||
36 | + 'Meta': {'object_name': 'User'}, | ||
37 | + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
38 | + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), | ||
39 | + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
40 | + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), | ||
41 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
42 | + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), | ||
43 | + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
44 | + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
45 | + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), | ||
46 | + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), | ||
47 | + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), | ||
48 | + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), | ||
49 | + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) | ||
50 | + }, | ||
51 | + 'contenttypes.contenttype': { | ||
52 | + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, | ||
53 | + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
54 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
55 | + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), | ||
56 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) | ||
57 | + }, | ||
58 | + 'super_archives.emailaddress': { | ||
59 | + 'Meta': {'object_name': 'EmailAddress'}, | ||
60 | + 'address': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}), | ||
61 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
62 | + 'md5': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
63 | + 'real_name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '64', 'blank': 'True'}), | ||
64 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'emails'", 'null': 'True', 'to': "orm['auth.User']"}) | ||
65 | + }, | ||
66 | + 'super_archives.mailinglist': { | ||
67 | + 'Meta': {'object_name': 'MailingList'}, | ||
68 | + 'description': ('django.db.models.fields.TextField', [], {}), | ||
69 | + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}), | ||
70 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
71 | + 'last_imported_index': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
72 | + 'logo': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}), | ||
73 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80'}) | ||
74 | + }, | ||
75 | + 'super_archives.mailinglistmembership': { | ||
76 | + 'Meta': {'object_name': 'MailingListMembership'}, | ||
77 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
78 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
79 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
80 | + }, | ||
81 | + 'super_archives.message': { | ||
82 | + 'Meta': {'object_name': 'Message'}, | ||
83 | + 'body': ('django.db.models.fields.TextField', [], {'default': "''"}), | ||
84 | + 'from_address': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.EmailAddress']"}), | ||
85 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
86 | + 'message_id': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
87 | + 'received_time': ('django.db.models.fields.DateTimeField', [], {}), | ||
88 | + 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
89 | + 'subject': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), | ||
90 | + 'subject_clean': ('django.db.models.fields.CharField', [], {'max_length': '512', 'db_index': 'True'}), | ||
91 | + 'thread': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Thread']", 'null': 'True'}) | ||
92 | + }, | ||
93 | + 'super_archives.messagemetadata': { | ||
94 | + 'Message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
95 | + 'Meta': {'object_name': 'MessageMetadata'}, | ||
96 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
97 | + 'name': ('django.db.models.fields.CharField', [], {'max_length': '512'}), | ||
98 | + 'value': ('django.db.models.fields.TextField', [], {}) | ||
99 | + }, | ||
100 | + 'super_archives.pagehit': { | ||
101 | + 'Meta': {'object_name': 'PageHit'}, | ||
102 | + 'hit_count': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
103 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
104 | + 'url_path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '2048', 'db_index': 'True'}) | ||
105 | + }, | ||
106 | + 'super_archives.thread': { | ||
107 | + 'Meta': {'unique_together': "(('subject_token', 'mailinglist'),)", 'object_name': 'Thread'}, | ||
108 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
109 | + 'latest_message': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'+'", 'unique': 'True', 'null': 'True', 'to': "orm['super_archives.Message']"}), | ||
110 | + 'mailinglist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.MailingList']"}), | ||
111 | + 'score': ('django.db.models.fields.IntegerField', [], {'default': '0'}), | ||
112 | + 'spam': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), | ||
113 | + 'subject_token': ('django.db.models.fields.CharField', [], {'max_length': '512'}) | ||
114 | + }, | ||
115 | + 'super_archives.userprofile': { | ||
116 | + 'Meta': {'object_name': 'UserProfile'}, | ||
117 | + 'facebook': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
118 | + 'google_talk': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True'}), | ||
119 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
120 | + 'institution': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
121 | + 'role': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
122 | + 'twitter': ('django.db.models.fields.CharField', [], {'max_length': '128', 'null': 'True'}), | ||
123 | + 'user': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['auth.User']", 'unique': 'True'}), | ||
124 | + 'verification_hash': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True'}), | ||
125 | + 'webpage': ('django.db.models.fields.CharField', [], {'max_length': '256'}) | ||
126 | + }, | ||
127 | + 'super_archives.vote': { | ||
128 | + 'Meta': {'unique_together': "(('user', 'message'),)", 'object_name': 'Vote'}, | ||
129 | + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), | ||
130 | + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), | ||
131 | + 'message': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['super_archives.Message']"}), | ||
132 | + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) | ||
133 | + } | ||
134 | + } | ||
135 | + | ||
136 | + complete_apps = ['super_archives'] |
colab/super_archives/models.py
@@ -194,6 +194,14 @@ class Message(models.Model): | @@ -194,6 +194,14 @@ class Message(models.Model): | ||
194 | return '(%s) %s: %s' % (self.id, | 194 | return '(%s) %s: %s' % (self.id, |
195 | self.from_address.get_full_name(), | 195 | self.from_address.get_full_name(), |
196 | self.subject_clean) | 196 | self.subject_clean) |
197 | + | ||
198 | + @property | ||
199 | + def mailinglist(self): | ||
200 | + if not self.thread or not self.thread.mailinglist: | ||
201 | + return None | ||
202 | + | ||
203 | + return self.thread.mailinglist | ||
204 | + | ||
197 | 205 | ||
198 | def vote_list(self): | 206 | def vote_list(self): |
199 | """Return a list of user that voted in this message.""" | 207 | """Return a list of user that voted in this message.""" |
colab/super_archives/queries.py
@@ -28,7 +28,7 @@ def get_messages_by_voted(): | @@ -28,7 +28,7 @@ def get_messages_by_voted(): | ||
28 | 28 | ||
29 | def get_first_message_in_thread(mailinglist, thread_token): | 29 | def get_first_message_in_thread(mailinglist, thread_token): |
30 | query = get_messages_by_date() | 30 | query = get_messages_by_date() |
31 | - query = query.filter(mailinglist__name=mailinglist) | 31 | + query = query.filter(thread__mailinglist__name=mailinglist) |
32 | query = query.filter(thread__subject_token=thread_token)[0] | 32 | query = query.filter(thread__subject_token=thread_token)[0] |
33 | return query | 33 | return query |
34 | 34 |
colab/super_archives/views.py
@@ -18,7 +18,7 @@ def thread(request, mailinglist, thread_token): | @@ -18,7 +18,7 @@ def thread(request, mailinglist, thread_token): | ||
18 | msgs_query = queries.get_messages_by_date() | 18 | msgs_query = queries.get_messages_by_date() |
19 | 19 | ||
20 | msgs_query = msgs_query.filter(thread__subject_token=thread_token) | 20 | msgs_query = msgs_query.filter(thread__subject_token=thread_token) |
21 | - msgs_query = msgs_query.filter(mailinglist__name=mailinglist) | 21 | + msgs_query = msgs_query.filter(thread__mailinglist__name=mailinglist) |
22 | emails = msgs_query.exclude(id=first_message.id) | 22 | emails = msgs_query.exclude(id=first_message.id) |
23 | 23 | ||
24 | total_votes = first_message.votes_count() | 24 | total_votes = first_message.votes_count() |
colab/templates/base.html
@@ -137,6 +137,7 @@ | @@ -137,6 +137,7 @@ | ||
137 | 137 | ||
138 | <div id="footer" class="span-24 center"> | 138 | <div id="footer" class="span-24 center"> |
139 | {% block footer %} | 139 | {% block footer %} |
140 | + <p><a href="{% url opendata %}"><img src="{{ STATIC_URL }}img/opendata3.png"/></a></p> | ||
140 | <p>O conteúdo deste site está publicado sob a licença <a | 141 | <p>O conteúdo deste site está publicado sob a licença <a |
141 | href="http://creativecommons.org/licenses/by-nc-sa/2.0/br/">Creative | 142 | href="http://creativecommons.org/licenses/by-nc-sa/2.0/br/">Creative |
142 | Commons - atribuição e não-comercial</a> | 143 | Commons - atribuição e não-comercial</a> |
@@ -0,0 +1,84 @@ | @@ -0,0 +1,84 @@ | ||
1 | +{% extends "base.html" %} | ||
2 | +{% load i18n %} | ||
3 | + | ||
4 | +{% block main-content %} | ||
5 | + <div class="span-18"> | ||
6 | + {% blocktrans %} | ||
7 | + <h2>Dados abertos - Comunidades Interlegis</h2> | ||
8 | + <p>Neste momento o sistema Colab disponibiliza grande parte de seus dados | ||
9 | + através do seu sistema de buscas.</p> | ||
10 | + <p>Caso você esteja interessado em integrar seu sistema com o ambiente Colab | ||
11 | + e necessite de outros dados não fornecidos por esta API, por favor | ||
12 | + entre em contato conosco através do sistemas de tiquetes (é necessário | ||
13 | + estar cadastrado para criar um tiquete).</p> | ||
14 | + | ||
15 | + <h3>Realizando buscas através da API</h3> | ||
16 | + <p>A API de buscas do Colab funciona através de um serviço HTTP/REST sempre | ||
17 | + retornando objetos JSON com resultado. </p> | ||
18 | + <p>A URL base utilizada para a busca é: | ||
19 | + <a href="/api/search/">http://colab.interlegis.leg.br/api/search/</a></p> | ||
20 | + | ||
21 | + <h3>Parâmetros:</h3> | ||
22 | + <ul class="prepend-1"> | ||
23 | + <li> | ||
24 | + <h4><i>Query</i> - q</h4> | ||
25 | + A <i>query</i> é a "pergunta" enviada | ||
26 | + para o servidor de buscas. Uma <i>query</i> é composta por | ||
27 | + <b>campo:valor</b>, onde campo representa um tipo de dados do sistema, | ||
28 | + por exemplo <b>collaborator</b> e valor representa o dado armazenado | ||
29 | + pelo sistema, por exemplo <b>jeanferri</b>. | ||
30 | + Segue a lista de campos disponíveis para a busca: | ||
31 | + <ul class="prepend-1"> | ||
32 | + <li><b><br/> | ||
33 | + Type</b>: wiki, thread, ticket, changeset.</li> | ||
34 | + <li><b>Title</b>: nome da página, título da discussão ou tiquete, descrição do changeset.</li> | ||
35 | + <li><b>Description</b>: trecho da página ou da discussão, descrição do tíquete ou changeset.</li> | ||
36 | + <li><b>Creator</b>: nome de usuário de quem criou o documento.</li> | ||
37 | + <li><b>creator_real_name</b>: nome real de quem criou o documento.</li> | ||
38 | + <li><b>create</b>: data de criação.</li> | ||
39 | + <li><b>modified</b>: data de modificação.</li> | ||
40 | + <li><b>mailinglist</b>: lista de discussões (apenas para o tipo thread).</li> | ||
41 | + <li><b>name</b>: nome da página wiki.</li> | ||
42 | + <li><b>comment</b>: comentários dos tíquetes (todos concatenados).</li> | ||
43 | + <li><b>content</b>: contúdo da página wiki ou mensagens da discussão (todas concatenadas). </li> | ||
44 | + <li><b>keyword</b>: keywords (apenas para tíquete).</li> | ||
45 | + <li><b>milestone</b>: milestone (apenas para tíquete).</li> | ||
46 | + <li><b>priority</b>: prioridade (apenas para tíquete).</li> | ||
47 | + <li><b>component</b>: componente (apenas para tíquete).</li> | ||
48 | + <li><b>version</b>: versão (apenas para tíquete).</li> | ||
49 | + <li><b>severity</b>: severidade (apenas para tíquete).</li> | ||
50 | + <li><b>owner</b>: responsável (apenas para tíquete).</li> | ||
51 | + <li><b>status</b>: status (apenas para tíquete).</li> | ||
52 | + <li><b>revision</b>: revisão (apenas para tíquete).</li> | ||
53 | + <li><b>subject</b>: sinônimo de título (apenas para discussões).</li> | ||
54 | + </ul> | ||
55 | + </li> | ||
56 | + <br/><hr/> | ||
57 | + | ||
58 | + <li> | ||
59 | + <h4>Resultados por Página - n </h4> | ||
60 | + Número de resultados que devem ser exibidos por página. Seu | ||
61 | + valor deveser um número inteiro entre 1 e 500. | ||
62 | + <i>Default: 50</i>. | ||
63 | + </li> | ||
64 | + <br/><hr/> | ||
65 | + | ||
66 | + <li> | ||
67 | + <h4>Página - p</h4> | ||
68 | + Número da página que será exibida. Seu valor deve ser um | ||
69 | + número inteiro igual ou maior que 1. <i>Default: 1</i>. | ||
70 | + </li> | ||
71 | + <br/><hr/> | ||
72 | + | ||
73 | + <li> | ||
74 | + <h4>Ordem - o</h4> | ||
75 | + Ordem em que os resultados serão exibidos. Seu valor deve | ||
76 | + ser uma string no formato <b>campo direção</b> onde campo | ||
77 | + são os mesmos apresentados no parametro <i>query</i> e | ||
78 | + direção pode ser <b>asc</b> para ascendente ou <b>desc</b> | ||
79 | + para descendente. <i>Default: score desc</i>. | ||
80 | + </li> | ||
81 | + <br/> | ||
82 | + </ul> | ||
83 | + {% endblocktrans %} | ||
84 | +{% endblock %} |
colab/urls.py
1 | from django.conf.urls.defaults import patterns, include, url | 1 | from django.conf.urls.defaults import patterns, include, url |
2 | +from django.views.generic.simple import direct_to_template | ||
2 | 3 | ||
3 | # Uncomment the next two lines to enable the admin: | 4 | # Uncomment the next two lines to enable the admin: |
4 | from django.contrib import admin | 5 | from django.contrib import admin |
@@ -8,11 +9,14 @@ urlpatterns = patterns('', | @@ -8,11 +9,14 @@ urlpatterns = patterns('', | ||
8 | url(r'^$', 'colab.views.other.home', name='home'), | 9 | url(r'^$', 'colab.views.other.home', name='home'), |
9 | 10 | ||
10 | url(r'^archives/', include('colab.super_archives.urls')), | 11 | url(r'^archives/', include('colab.super_archives.urls')), |
11 | - | 12 | + |
12 | url(r'^api/', include('colab.api.urls')), | 13 | url(r'^api/', include('colab.api.urls')), |
13 | 14 | ||
14 | url(r'^rss/', include('colab.rss.urls')), | 15 | url(r'^rss/', include('colab.rss.urls')), |
15 | 16 | ||
17 | + url(r'open-data/$', direct_to_template, {'template': 'open-data.html'}, | ||
18 | + name='opendata'), | ||
19 | + | ||
16 | url(r'^user/(?P<username>[\w@+.-]+)/?$', | 20 | url(r'^user/(?P<username>[\w@+.-]+)/?$', |
17 | 'colab.views.userprofile.by_username', name='user_profile'), | 21 | 'colab.views.userprofile.by_username', name='user_profile'), |
18 | 22 |
etc/apache2/sites-available/colab
@@ -23,6 +23,7 @@ | @@ -23,6 +23,7 @@ | ||
23 | RewriteRule ^/query(.*) http://colab-backend.interlegis.leg.br/query$1 [P] | 23 | RewriteRule ^/query(.*) http://colab-backend.interlegis.leg.br/query$1 [P] |
24 | RewriteRule ^/about(.*) http://colab-backend.interlegis.leg.br/about$1 [P] | 24 | RewriteRule ^/about(.*) http://colab-backend.interlegis.leg.br/about$1 [P] |
25 | RewriteRule ^/prefs(.*) http://colab-backend.interlegis.leg.br/prefs$1 [P] | 25 | RewriteRule ^/prefs(.*) http://colab-backend.interlegis.leg.br/prefs$1 [P] |
26 | + RewriteRule ^/log(.*) http://colab-backend.interlegis.leg.br/log$1 [P] | ||
26 | RewriteRule ^/login(.*) http://colab-backend.interlegis.leg.br/login$1 [P] | 27 | RewriteRule ^/login(.*) http://colab-backend.interlegis.leg.br/login$1 [P] |
27 | RewriteRule ^/logout(.*) http://colab-backend.interlegis.leg.br/logout$1 [P] | 28 | RewriteRule ^/logout(.*) http://colab-backend.interlegis.leg.br/logout$1 [P] |
28 | RewriteRule ^/attachment(.*) http://colab-backend.interlegis.leg.br/attachment$1 [P] | 29 | RewriteRule ^/attachment(.*) http://colab-backend.interlegis.leg.br/attachment$1 [P] |
setup.py
@@ -4,7 +4,7 @@ from setuptools import setup, find_packages | @@ -4,7 +4,7 @@ from setuptools import setup, find_packages | ||
4 | from setupext import Data_Files, install_Data_Files | 4 | from setupext import Data_Files, install_Data_Files |
5 | 5 | ||
6 | setup(name='colab', | 6 | setup(name='colab', |
7 | - version='0.1-dev', | 7 | + version='3.0', |
8 | author='Sergio Oliveira', | 8 | author='Sergio Oliveira', |
9 | author_email='seocam@seocam.com', | 9 | author_email='seocam@seocam.com', |
10 | url='https://bitbucket.org/seocam/atu-colab', | 10 | url='https://bitbucket.org/seocam/atu-colab', |