Commit aa8a55a47e16c568f2eb08ad4bd3a241d210db73

Authored by Luan
2 parents 232e9e6a 358a1621

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

TODO.rst
1 1 TODO
2 2 -----
3 3  
4   -Gestão de listas
5   -================
  4 +Emails
  5 +=======
  6 +* Atualizar versão do Mailman
6 7 * Sincronizar informações de membership do mailman com o django
7 8 * Usar informações do banco de dados local ao inves de fazer queries constantes
8 9 * Logar erros ao falhar inscricao ou remocao de listas
9 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 17 Updates
... ... @@ -20,12 +25,6 @@ Async
20 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 28 Planet
30 29 ======
31 30  
... ... @@ -38,51 +37,22 @@ Chat
38 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 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 52 * Criacao de repositorios distribuidos pela interface do colab
61   -* Link para última msg recebida na thread
62 53 * Fazer thread querysets ter um objeto (most_relevant_message)
63   -* Implementar enviar email
64 54 * BUG: alguns subjects comecam e terminam com [] fazendo com que a RE de limpeza apague todo o subject.
65 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 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 57 * Indice criado manualmente. Automatizar:
88 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 2 South==0.8.1
4 3 psycopg2==2.5.1
5 4 django-piston==0.2.3
... ... @@ -25,7 +24,7 @@ raven
25 24 tornado
26 25  
27 26 # Deps for Single SignOn (SSO)
28   -django-browserid
  27 +git+https://github.com/TracyWebTech/django-browserid@issue210
29 28 django-revproxy
30 29  
31 30 # Converse.js (XMPP client)
... ...
src/super_archives/management/commands/import_emails.py
... ... @@ -13,10 +13,10 @@ from django.db import transaction
13 13 from django.template.defaultfilters import slugify
14 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 22 class Command(BaseCommand, object):
... ...
src/super_archives/urls.py
1 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 6 urlpatterns = patterns('super_archives.views',
7 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 10 url(r'thread/$', 'list_messages', name='thread_list'),
11 11 url(r'manage/email/validate/?$', EmailValidationView.as_view(),
12 12 name="archive_email_validation_view"),
... ...
src/super_archives/views.py
... ... @@ -23,96 +23,89 @@ from .utils.email import send_verification_email
23 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 111 def list_messages(request):
... ...