Commit aa8a55a47e16c568f2eb08ad4bd3a241d210db73

Authored by Luan
2 parents 232e9e6a 358a1621

Merge branch 'master' of github.com:TracyWebTech/colab

1 TODO 1 TODO
2 ----- 2 -----
3 3
4 -Gestão de listas  
5 -================ 4 +Emails
  5 +=======
  6 +* Atualizar versão do Mailman
6 * Sincronizar informações de membership do mailman com o django 7 * Sincronizar informações de membership do mailman com o django
7 * Usar informações do banco de dados local ao inves de fazer queries constantes 8 * Usar informações do banco de dados local ao inves de fazer queries constantes
8 * Logar erros ao falhar inscricao ou remocao de listas 9 * Logar erros ao falhar inscricao ou remocao de listas
9 * Processo de cadastro em listas com moderacao 10 * Processo de cadastro em listas com moderacao
  11 +* Permitir moderacao de mensagens pelo Colab
  12 +* Permitir a gestao de listas pelo Colab
  13 +* Não perder o email em caso de falha de envio. Exibir o erro mas trazer a mensagem de volta para o usuário
  14 +* Permitir apenas que usuarios pertencentes a lista enviem mensagens
10 15
11 16
12 Updates 17 Updates
@@ -20,12 +25,6 @@ Async @@ -20,12 +25,6 @@ Async
20 * Usar celery para tornar tasks como envio de emails asincronas. 25 * Usar celery para tornar tasks como envio de emails asincronas.
21 26
22 27
23 -Envio de emails  
24 -===============  
25 -* Não perder o email em caso de falha de envio. Exibir o erro mas trazer a mensagem de volta para o usuário  
26 -* Permitir apenas que usuarios pertencentes a lista enviem mensagens  
27 -  
28 -  
29 Planet 28 Planet
30 ====== 29 ======
31 30
@@ -38,51 +37,22 @@ Chat @@ -38,51 +37,22 @@ Chat
38 * Permitir que usuario altere senha 37 * Permitir que usuario altere senha
39 38
40 39
  40 +Interface
  41 +=========
  42 +
  43 +* Utilizar paginador do bootstrap 3 em todas as telas
  44 +* Implementar breadcrumbs
  45 +* Utilizar biblioteca de gráficos local (substituir google charts)
  46 +* Melhorar filtros para interfaces móveis
  47 +
  48 +
41 Outros 49 Outros
42 ======= 50 =======
43 51
44 -* Adicionar data do ultimo import de emails no footer  
45 -* Detectar links no conteudo e exibi-los como tal  
46 -* BUG: Display of HTML emails are wrong  
47 -* Arquivo "search.html" existente em "atu-colab/colab/templates" pode ser melhorado com relação ao conteúdo repetitivo dos "Tipos" exibidos no "Filtro" da página  
48 -* BUG: Criar validador de urls para twitter, facebook e página pessoal do user profile  
49 -* Mostrar dados do twitter, facebook, gtalk e página pessoal somente para os usuários que estiverem logados  
50 -* Configurar ADMINS no arquivo settings_local.py  
51 -* HTTPS para o trac, subversion e colab  
52 -  
53 -* Quando usuario se cadastra com email errado o email nunca eh validado, e o username fica preso 'pra sempre'.  
54 -* Nome dos usuarios errado nos emails que vem do Solr  
55 -* Adicionar ordering na busca  
56 -* Criar tipo usuario no solr  
57 -* Utilizar haystack  
58 -* Melhorar buscas (case insensitive match, palavras com acentos)  
59 -* Indexar nome do repositorio como campo e exibi-lo no titulo dos changesets retornados  
60 * Criacao de repositorios distribuidos pela interface do colab 52 * Criacao de repositorios distribuidos pela interface do colab
61 -* Link para última msg recebida na thread  
62 * Fazer thread querysets ter um objeto (most_relevant_message) 53 * Fazer thread querysets ter um objeto (most_relevant_message)
63 -* Implementar enviar email  
64 * BUG: alguns subjects comecam e terminam com [] fazendo com que a RE de limpeza apague todo o subject. 54 * BUG: alguns subjects comecam e terminam com [] fazendo com que a RE de limpeza apague todo o subject.
65 * BUG: mensagens importadas por listas erradas 55 * BUG: mensagens importadas por listas erradas
66 -* Claime email address  
67 -* Merge emails dos usuarios  
68 -* Implementar badge system  
69 -* Melhorar filtros  
70 -* Link do thread preview deve enviar para mensagem da thread (anchor)  
71 -* Indexar anexos da wiki (using Tika http://wiki.apache.org/solr/ExtractingRequestHandler)  
72 -* Filtrar usando calendario (como google analytics)  
73 -* Melhorar relevancia das buscas usando dismax queryparser  
74 -* Exibir discussões relacionadas na barra da direita das discussões  
75 * Migração e reorganização do conteúdo do trac/wiki para o novo colab 56 * Migração e reorganização do conteúdo do trac/wiki para o novo colab
76 -* Ao importar mensagem sem subject enviar email avisando o usuario que ele esta enviando um email sem o campos "Assunto"  
77 -* Remover ou ocultar trechos da mensagem que iniciem com ">" assim como o Gmail.  
78 -* Contar page views no trac (ticket, wiki e changeset) e utiliza-los para rankear paginas nas buscas  
79 -* Mostrar highlight nas buscas  
80 -* Sistema de tags para as mensagens  
81 -* Tag cloud para as mensagens, ao lado direito da thread  
82 -* Pagina home para cada lista com os mesmo filtros da home atual  
83 -* Permitir que usuario entre e saia de listas ao editar perfil  
84 -* Filtros específicos para tipos diferentes na busca da thread  
85 -* Link para a mensagem original no histórico do Mailman (popup ajax)  
86 -* Filtro de mensagens nas listas acumulativos, podendo ligar e desligar todos  
87 * Indice criado manualmente. Automatizar: 57 * Indice criado manualmente. Automatizar:
88 * create index super_archives_message_body_idx ON super_archives_message ((substring(body,0,1024))); 58 * create index super_archives_message_body_idx ON super_archives_message ((substring(body,0,1024)));
requirements.txt
1 -https://www.djangoproject.com/download/1.6c1/tarball/  
2 -#Django==1.5.2 1 +Django>=1.6,<1.7
3 South==0.8.1 2 South==0.8.1
4 psycopg2==2.5.1 3 psycopg2==2.5.1
5 django-piston==0.2.3 4 django-piston==0.2.3
@@ -25,7 +24,7 @@ raven @@ -25,7 +24,7 @@ raven
25 tornado 24 tornado
26 25
27 # Deps for Single SignOn (SSO) 26 # Deps for Single SignOn (SSO)
28 -django-browserid 27 +git+https://github.com/TracyWebTech/django-browserid@issue210
29 django-revproxy 28 django-revproxy
30 29
31 # Converse.js (XMPP client) 30 # Converse.js (XMPP client)
src/super_archives/management/commands/import_emails.py
@@ -13,10 +13,10 @@ from django.db import transaction @@ -13,10 +13,10 @@ from django.db import transaction
13 from django.template.defaultfilters import slugify 13 from django.template.defaultfilters import slugify
14 from django.core.management.base import BaseCommand, CommandError 14 from django.core.management.base import BaseCommand, CommandError
15 15
16 -from colab.super_archives.models import MailingList, Message, \  
17 - Thread, EmailAddress  
18 -from colab.super_archives.management.commands.message import Message as \  
19 - CustomMessage 16 +from super_archives.models import MailingList, Message, \
  17 + Thread, EmailAddress
  18 +from super_archives.management.commands.message import Message as \
  19 + CustomMessage
20 20
21 21
22 class Command(BaseCommand, object): 22 class Command(BaseCommand, object):
src/super_archives/urls.py
1 from django.conf.urls import patterns, include, url 1 from django.conf.urls import patterns, include, url
2 2
3 -from .views import EmailView, EmailValidationView 3 +from .views import EmailView, EmailValidationView, ThreadView
4 4
5 5
6 urlpatterns = patterns('super_archives.views', 6 urlpatterns = patterns('super_archives.views',
7 # url(r'thread/(?P<thread>\d+)/$', 'thread', name='thread'), 7 # url(r'thread/(?P<thread>\d+)/$', 'thread', name='thread'),
8 - url(r'thread/(?P<mailinglist>[-\w]+)/(?P<thread_token>[-\w]+)$', 'thread',  
9 - name="thread_view"), 8 + url(r'thread/(?P<mailinglist>[-\w]+)/(?P<thread_token>[-\w]+)$',
  9 + ThreadView.as_view(), name="thread_view"),
10 url(r'thread/$', 'list_messages', name='thread_list'), 10 url(r'thread/$', 'list_messages', name='thread_list'),
11 url(r'manage/email/validate/?$', EmailValidationView.as_view(), 11 url(r'manage/email/validate/?$', EmailValidationView.as_view(),
12 name="archive_email_validation_view"), 12 name="archive_email_validation_view"),
src/super_archives/views.py
@@ -23,96 +23,89 @@ from .utils.email import send_verification_email @@ -23,96 +23,89 @@ from .utils.email import send_verification_email
23 from .models import MailingList, Thread, EmailAddress, EmailAddressValidation 23 from .models import MailingList, Thread, EmailAddress, EmailAddressValidation
24 24
25 25
26 -def thread(request, mailinglist, thread_token):  
27 - if request.method == 'GET':  
28 - return thread_get(request, mailinglist, thread_token)  
29 - elif request.method == 'POST':  
30 - return thread_post(request, mailinglist, thread_token)  
31 - else:  
32 - return HttpResponseNotAllowed(['HEAD', 'GET', 'POST'])  
33 - 26 +class ThreadView(View):
  27 + http_method_names = [u'get', u'post']
34 28
35 -def thread_get(request, mailinglist, thread_token):  
36 - try:  
37 - first_message = queries.get_first_message_in_thread(mailinglist,  
38 - thread_token)  
39 - except ObjectDoesNotExist:  
40 - raise http.Http404 29 + def get(self, request, mailinglist, thread_token):
  30 + try:
  31 + first_message = queries.get_first_message_in_thread(mailinglist,
  32 + thread_token)
  33 + except ObjectDoesNotExist:
  34 + raise http.Http404
41 35
42 - thread = Thread.objects.get(subject_token=thread_token,  
43 - mailinglist__name=mailinglist)  
44 - thread.hit(request) 36 + thread = Thread.objects.get(subject_token=thread_token,
  37 + mailinglist__name=mailinglist)
  38 + thread.hit(request)
45 39
46 - order_by = request.GET.get('order')  
47 - if order_by == 'voted':  
48 - msgs_query = queries.get_messages_by_voted()  
49 - else:  
50 - msgs_query = queries.get_messages_by_date() 40 + order_by = request.GET.get('order')
  41 + if order_by == 'voted':
  42 + msgs_query = queries.get_messages_by_voted()
  43 + else:
  44 + msgs_query = queries.get_messages_by_date()
51 45
52 - msgs_query = msgs_query.filter(thread__subject_token=thread_token)  
53 - msgs_query = msgs_query.filter(thread__mailinglist__name=mailinglist)  
54 - emails = msgs_query.exclude(id=first_message.id) 46 + msgs_query = msgs_query.filter(thread__subject_token=thread_token)
  47 + msgs_query = msgs_query.filter(thread__mailinglist__name=mailinglist)
  48 + emails = msgs_query.exclude(id=first_message.id)
55 49
56 - total_votes = first_message.votes_count()  
57 - for email in emails:  
58 - total_votes += email.votes_count() 50 + total_votes = first_message.votes_count()
  51 + for email in emails:
  52 + total_votes += email.votes_count()
59 53
60 - # Update relevance score  
61 - thread.update_score() 54 + # Update relevance score
  55 + thread.update_score()
62 56
63 - context = {  
64 - 'first_msg': first_message,  
65 - 'emails': [first_message] + list(emails),  
66 - 'pagehits': thread.hits,  
67 - 'total_votes': total_votes,  
68 - 'thread': thread,  
69 - } 57 + context = {
  58 + 'first_msg': first_message,
  59 + 'emails': [first_message] + list(emails),
  60 + 'pagehits': thread.hits,
  61 + 'total_votes': total_votes,
  62 + 'thread': thread,
  63 + }
70 64
71 - return render(request, 'message-thread.html', context) 65 + return render(request, 'message-thread.html', context)
72 66
  67 + def post(self, request, mailinglist, thread_token):
  68 + try:
  69 + thread = Thread.objects.get(subject_token=thread_token,
  70 + mailinglist__name=mailinglist)
  71 + except Thread.DoesNotExist:
  72 + raise http.Http404
73 73
74 -def thread_post(request, mailinglist, thread_token):  
75 - try:  
76 - thread = Thread.objects.get(subject_token=thread_token,  
77 - mailinglist__name=mailinglist)  
78 - except Thread.DoesNotExist:  
79 - raise http.Http404  
80 -  
81 - data = {}  
82 - data['from'] = '{} <{}>'.format(request.user.get_full_name(),  
83 - request.user.email)  
84 - data['subject'] = thread.message_set.first().subject_clean  
85 - data['body'] = request.POST.get('emailbody', '').strip() 74 + data = {}
  75 + data['from'] = '{} <{}>'.format(request.user.get_full_name(),
  76 + request.user.email)
  77 + data['subject'] = thread.message_set.first().subject_clean
  78 + data['body'] = request.POST.get('emailbody', '').strip()
86 79
87 - url = urlparse.urljoin(settings.MAILMAN_API_URL, mailinglist + '/sendmail') 80 + url = urlparse.urljoin(settings.MAILMAN_API_URL, mailinglist + '/sendmail')
88 81
89 - error_msg = None  
90 - try:  
91 - resp = requests.post(url, data=data, timeout=2)  
92 - except requests.exceptions.ConnectionError:  
93 - resp = None  
94 - error_msg = _('Error trying to connect to Mailman API')  
95 - except requests.exceptions.Timeout:  
96 - resp = None  
97 - error_msg = _('Timout trying to connect to Mailman API')  
98 -  
99 - if resp and resp.status_code == 200:  
100 - messages.success(request, _("Your message was sent. It may take "  
101 - "some minutes before it's delivered. "  
102 - "Why don't you breath some fresh air "  
103 - "in the meanwhile."))  
104 - else:  
105 - if not error_msg:  
106 - if resp is not None:  
107 - if resp.status_code == 400:  
108 - error_msg = _('You cannot send an empty email')  
109 - elif resp.status_code == 404:  
110 - error_msg = _('Mailing list does not exist')  
111 - else:  
112 - error_msg = _('Unkown error trying to connect to Mailman API')  
113 - messages.error(request, error_msg)  
114 -  
115 - return thread_get(request, mailinglist, thread_token) 82 + error_msg = None
  83 + try:
  84 + resp = requests.post(url, data=data, timeout=2)
  85 + except requests.exceptions.ConnectionError:
  86 + resp = None
  87 + error_msg = _('Error trying to connect to Mailman API')
  88 + except requests.exceptions.Timeout:
  89 + resp = None
  90 + error_msg = _('Timout trying to connect to Mailman API')
  91 +
  92 + if resp and resp.status_code == 200:
  93 + messages.success(request, _("Your message was sent. It may take "
  94 + "some minutes before it's delivered. "
  95 + "Why don't you breath some fresh air "
  96 + "in the meanwhile."))
  97 + else:
  98 + if not error_msg:
  99 + if resp is not None:
  100 + if resp.status_code == 400:
  101 + error_msg = _('You cannot send an empty email')
  102 + elif resp.status_code == 404:
  103 + error_msg = _('Mailing list does not exist')
  104 + else:
  105 + error_msg = _('Unkown error trying to connect to Mailman API')
  106 + messages.error(request, error_msg)
  107 +
  108 + return self.get(request, mailinglist, thread_token)
116 109
117 110
118 def list_messages(request): 111 def list_messages(request):