Commit 491ecf50361a0c287444bce535e5cf8c447eed0d

Authored by Luan
2 parents b1ed6d3f f8695e46

Merge branch 'master' into hitcounter

TODO.rst
1 1 TODO
2 2 -----
3 3  
  4 +Envio de emails
  5 +===============
  6 +* Não perder o email em caso de falha de envio. Exibir o erro mas trazer a mensagem de volta para o usuário
  7 +
4 8 Planet
5 9 ======
6 10  
... ...
fabfile.py
... ... @@ -89,13 +89,18 @@ def deploy(update=False):
89 89 sudo('supervisorctl restart all')
90 90  
91 91  
92   -def rebuild_index(age=None):
  92 +def rebuild_index(age=None, batch=None):
93 93 with cd('~/colab/src/'), prefix(WORKON_COLAB):
94 94 age_arg = ''
95 95 if age:
96 96 age_arg = '--age={}'.format(age)
97 97  
98   - run('python manage.py rebuild_index {}'.format(age_arg))
  98 + batch_arg = ''
  99 + if batch:
  100 + batch_arg = '--batch-size={}'.format(batch)
  101 +
  102 +
  103 + run('python manage.py rebuild_index {} {}'.format(age_arg, batch_arg))
99 104  
100 105  
101 106 @with_settings(user='vagrant')
... ...
requirements.txt
... ... @@ -42,4 +42,4 @@ transliterate
42 42  
43 43 # Diazo
44 44 #diazo
45   -git+https://github.com/TracyWebTech/diazo@escape_curly_brackets
  45 +git+https://github.com/plone/diazo@44ca0da7de5a7ee5d4085c7344701b9cfecfb419
... ...
src/colab/custom_settings.py
... ... @@ -259,6 +259,10 @@ FEEDZILLA_SITE_TITLE = gettext(u'Planet Colab')
259 259 FEEDZILLA_SITE_DESCRIPTION = gettext(u'Colab blog aggregator')
260 260  
261 261  
  262 +### Mailman API settings
  263 +MAILMAN_API_URL = 'http://listas.interlegis.gov.br:8000'
  264 +
  265 +
262 266 ### BrowserID / Persona
263 267 SITE_URL = 'https://colab.interlegis.leg.br'
264 268 BROWSERID_AUDIENCES = [SITE_URL]
... ...
src/static/css/screen.css
... ... @@ -216,6 +216,10 @@ ul.unstyled-list .glyphicon-chevron-right {
216 216 margin-top: 1em;
217 217 }
218 218  
  219 +.reply.btn {
  220 + margin-left: 1em;
  221 +}
  222 +
219 223 .email-message pre {
220 224 border: 0;
221 225 background-color: #fff;
... ...
src/super_archives/templates/message-thread.html
1 1 {% extends "base.html" %}
2   -{% load i18n gravatar superarchives %}
  2 +{% load i18n superarchives %}
3 3  
4 4 {% trans "Anonymous" as anonymous %}
5 5  
... ... @@ -68,6 +68,19 @@
68 68 $ajax.fail(vote_fail_callback);
69 69 }
70 70  
  71 + function scrollToAnchor(aid){
  72 + var aTag = $(aid);
  73 + console.log(aTag);
  74 + $('html, body').animate({scrollTop: aTag.offset().top}, 800);
  75 + }
  76 +
  77 + {% if user.is_active %}
  78 + function focus_reply(event) {
  79 + scrollToAnchor('#msg-reply');
  80 + $('textarea', '#msg-reply').focus();
  81 + }
  82 + {% endif %}
  83 +
71 84 // Binding functions
72 85 $(function() {
73 86 $(".panel-heading").on('click', function(event) {
... ... @@ -82,6 +95,7 @@
82 95 });
83 96  
84 97 $('.vote.btn', this).on('click', vote);
  98 + $('.reply.btn', this).on('click', focus_reply);
85 99 });
86 100  
87 101 </script>
... ... @@ -99,56 +113,12 @@
99 113 <div class="col-lg-9 col-md-9 col-sm-12">
100 114 <ul class="unstyled-list">
101 115 {% for email in emails %}
102   - {% with email.from_address.user.get_absolute_url as profile_link %}
103   - <li>
104   - {% spaceless %}
105   - <div class="email-message" id="msg-{{ email.id }}">
106   - <div class="panel panel-default">
107   - <div class="panel-heading clearfix">
108   - <div class="col-lg-6 col-md-6 col-sm-6">
109   - {% if profile_link %}
110   - <a href="{{ profile_link }}">
111   - {% endif %}
112   - {% gravatar email.from_address 34 %}
113   - <strong class="user-fullname">{{ email.from_address.get_full_name_or_anonymous }}</strong>
114   - {% if profile_link %}
115   - </a>
116   - {% endif %}
117   - </div>
118   -
119   - <div class="col-lg-6 col-md-6 col-sm-6">
120   - <div class="pull-right text-right">
121   - <span class="date">
122   - {{ email.received_time|date:'DATETIME_FORMAT' }}
123   - </span>
124   -
125   - <div class="btn-group">
126   - <button class="btn btn-default vote-count disabled">
127   - {{ email.votes_count }}
128   - </button>
129   - {% if user in email.vote_list %}
130   - <button class="btn btn-success vote" data-loading-text="...">
131   - {% else %}
132   - <button class="btn btn-default vote" data-loading-text="...">
133   - {% endif %}
134   - <span class="glyphicon glyphicon-thumbs-up"></span>
135   - </button>
136   - </div>
137   - </div>
138   - </div>
139   -
140   - </div>
141   - <div class="panel-collapse in">
142   - <div class="panel-body">
143   - {% display_message email %}
144   - </div>
145   - </div>
146   - </div>
147   - </div>
148   - {% endspaceless %}
149   - </li>
150   - {% endwith %}
  116 + {% include "superarchives/includes/message.html" with userprofile=email.from_address.user emailaddress=email.from_address fullname=email.from_address.get_full_name_or_anonymous %}
151 117 {% endfor %}
  118 +
  119 + {% if user.is_active %}
  120 + {% include "superarchives/includes/message.html" with userprofile=user emailaddress=user.email fullname=user.get_full_name reply=True %}
  121 + {% endif %}
152 122 </ul>
153 123 </div>
154 124  
... ...
src/super_archives/templates/superarchives/includes/message.html 0 → 100644
... ... @@ -0,0 +1,71 @@
  1 +{% load gravatar superarchives i18n %}
  2 +<li>
  3 + {% spaceless %}
  4 + <div class="email-message" id="msg-{% firstof email.id 'reply' %}">
  5 + <div class="panel panel-default">
  6 + <div class="panel-heading clearfix">
  7 + <div class="col-lg-6 col-md-6 col-sm-6">
  8 + {% if userprofile.get_absolute_url %}
  9 + <a href="{{ userprofile.get_absolute_url }}">
  10 + {% endif %}
  11 + {% gravatar emailaddress 34 %}
  12 + <strong class="user-fullname">{{ fullname }}</strong>
  13 + {% if userprofile.get_absolute_url %}
  14 + </a>
  15 + {% endif %}
  16 + </div>
  17 +
  18 + {% if not reply %}
  19 + <div class="col-lg-6 col-md-6 col-sm-6">
  20 + <div class="pull-right text-right">
  21 + <span class="date">
  22 + {{ email.received_time|date:'DATETIME_FORMAT' }}
  23 + </span>
  24 +
  25 + <div class="btn-group">
  26 + <button class="btn btn-default vote-count disabled">
  27 + {{ email.votes_count }}
  28 + </button>
  29 + {% if user in email.vote_list %}
  30 + <button class="btn btn-success vote" data-loading-text="...">
  31 + {% else %}
  32 + <button class="btn btn-default vote" data-loading-text="...">
  33 + {% endif %}
  34 + <span class="glyphicon glyphicon-thumbs-up"></span>
  35 + </button>
  36 + </div>
  37 +
  38 + {% if user.is_active %}
  39 + <button class="btn btn-default reply" title="{% trans 'Reply' %}">
  40 + <span class="glyphicon glyphicon-share"></span>
  41 + </button>
  42 + {% endif %}
  43 + </div>
  44 + </div>
  45 + {% endif %}
  46 +
  47 + </div>
  48 + <div class="panel-collapse in">
  49 + <div class="panel-body">
  50 + {% if not reply %}
  51 + {% display_message email %}
  52 + {% else %}
  53 + <form method="POST">
  54 + {% csrf_token %}
  55 + <p>
  56 + <textarea placeholder="{% trans 'Send a message' %}" rows="5" class="form-control"></textarea>
  57 + </p>
  58 + <div class="col-lg-9 col-md-8 col-sm-8 col-xs-7">
  59 + <p class="quiet">{% trans "After sending a message it will take few minutes before it shows up in here. Why don't you grab a coffee?" %}</p>
  60 + </div>
  61 + <div class="col-lg-3 col-md-4 col-sm-4 col-xs-5 text-right">
  62 + <button class="btn btn-success" type="submit">{% trans 'Send' %}</button>
  63 + </div>
  64 + </form>
  65 + {% endif %}
  66 + </div>
  67 + </div>
  68 + </div>
  69 + </div>
  70 +{% endspaceless %}
  71 +</li>
... ...
src/super_archives/views.py
... ... @@ -2,6 +2,9 @@
2 2  
3 3 import smtplib
4 4 import logging
  5 +import urlparse
  6 +
  7 +import requests
5 8  
6 9 from django import http
7 10 from django.conf import settings
... ... @@ -21,7 +24,15 @@ from .models import MailingList, Thread, EmailAddress, EmailAddressValidation
21 24  
22 25  
23 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 +
24 34  
  35 +def thread_get(request, mailinglist, thread_token):
25 36 try:
26 37 first_message = queries.get_first_message_in_thread(mailinglist,
27 38 thread_token)
... ... @@ -60,6 +71,47 @@ def thread(request, mailinglist, thread_token):
60 71 return render(request, 'message-thread.html', context)
61 72  
62 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['email_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('body', '').strip()
  86 +
  87 + url = urlparse.urljoin(settings.MAILMAN_API_URL, mailinglist + '/sendmail')
  88 +
  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 and resp.status_code == 400:
  107 + error_msg = _('You cannot send an empty email')
  108 + else:
  109 + error_msg = _('Unkown error trying to connect to Mailman API')
  110 + messages.error(request, error_msg)
  111 +
  112 + return thread_get(request, mailinglist, thread_token)
  113 +
  114 +
63 115 def list_messages(request):
64 116 selected_lists = request.GET.get('list', [])
65 117 if selected_lists:
... ...