add announce view (#15213)

This commit is contained in:
Serghei Mihai 2017-03-02 17:14:00 +01:00
parent b56be82b22
commit 06620ee794
10 changed files with 187 additions and 20 deletions

View File

@ -2,7 +2,7 @@ from django.conf.urls import patterns, include, url
from .views import add_announce, edit_announce, delete_announce, \
add_category, edit_category, view_category, delete_category, manage, \
subscriptions_import, menu_json
subscriptions_import, view_announce, menu_json
urlpatterns = patterns('',
url(r'^$', manage, name='manage'),
@ -14,6 +14,8 @@ urlpatterns = patterns('',
name='delete_announce'),
url(r'^category/(?P<slug>[\w-]+)/$', view_category,
name='view_category'),
url(r'^announce/(?P<pk>\d+)/$', view_announce,
name='view_announce'),
url(r'^category/add$', add_category,
name='add_category'),
url(r'^category/edit/(?P<slug>[\w-]+)$', edit_category,

View File

@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
def migrate_delivery_count(apps, schema_editor):
Broadcast = apps.get_model('corbo', 'Broadcast')
for broadcast in Broadcast.objects.all():
try:
broadcast.delivery_count = int(broadcast.result)
except ValueError:
broadcast.delivery_count = 0
broadcast.save()
def migrate_result(apps, schema_editor):
Broadcast = apps.get_model('corbo', 'Broadcast')
for broadcast in Broadcast.objects.all():
broadcast.result = str(broadcast.delivery_count)
broadcast.save()
class Migration(migrations.Migration):
dependencies = [
('corbo', '0009_auto_20170120_1533'),
]
operations = [
migrations.RunSQL('SET CONSTRAINTS ALL IMMEDIATE',
reverse_sql=migrations.RunSQL.noop),
migrations.AddField(
model_name='broadcast',
name='delivery_count',
field=models.IntegerField(default=0, verbose_name='Delivery count'),
),
migrations.RunPython(migrate_delivery_count, migrate_result),
migrations.RemoveField(
model_name='broadcast',
name='result',
),
migrations.RunSQL(migrations.RunSQL.noop,
reverse_sql='SET CONSTRAINTS ALL IMMEDIATE'),
]

View File

@ -161,7 +161,7 @@ class Announce(models.Model):
class Broadcast(models.Model):
announce = models.ForeignKey(Announce, verbose_name=_('announce'))
deliver_time = models.DateTimeField(_('Deliver time'), null=True)
result = models.TextField(_('result'), blank=True)
delivery_count = models.IntegerField(_('Delivery count'), default=0)
def __unicode__(self):
if self.deliver_time:
@ -201,7 +201,7 @@ class Broadcast(models.Model):
else:
logger.warning('Error occured while sending announce "%s" to %s.',
self.announce.title, s.identifier)
self.result = total_sent
self.delivery_count = total_sent
self.deliver_time = timezone.now()
self.save()

View File

@ -165,3 +165,36 @@ form ul li label {
border-radius: 0.3em;
text-transform: uppercase;
}
div.announce_block {
position: relative;
}
.announce_dashboard {
background: #eee;
font-size: 1.1em;
margin-left: 0.5em;
padding: 0.3rem;
width: 15%;
position: absolute;
right: 0;
top: 0;
}
.announce_dashboard p {
border-bottom: 1px solid #ccc;
padding: 0.5rem;
}
.announce_dashboard strong {
display: block;
}
.announce_dashboard p:last-child {
border: 0;
}
div.announce_preview {
width: 84%;
overflow: hidden;
}

View File

@ -3,15 +3,15 @@
{% block breadcrumb %}
{{ block.super }}
{% if category %}
<a href='{% url "view_category" slug=category.slug %}'>{{ category }}</a>
{% if object %}
<a href='{% url "view_announce" pk=object.pk %}'>{{ object.title }}</a>
{% endif %}
<a href='{% url "view_category" slug=category.slug %}'>{{ category }}</a>
{% endblock %}
{% block appbar %}
{% if object %}
<h2>{% trans "Edit Announce" %}</h2>
<a href='{% url "delete_announce" pk=object.pk %}' rel='popup'>{% trans 'Delete' %}</a>
{% else %}
<h2>{% trans "New Announce" %}</h2>
{% endif %}
@ -26,7 +26,7 @@
{{ form.as_p }}
<div class="buttons">
<button class="submit-button">{% trans "Save" %}</button>
<a class="cancel" href="{% url 'view_category' slug=category.slug %}">{% trans 'Cancel' %}</a>
<a class="cancel" href="{% if object %}{% url 'view_announce' pk=object.pk %}{% else %}{% url 'view_category' slug=category.slug %}{% endif %}">{% trans 'Cancel' %}</a>
</div>
</form>
{% endblock %}

View File

@ -26,7 +26,7 @@
<ul class='objects-list single-links'>
{% for announce in object_list %}
<li class="{% if not announce.is_published %}unpublished{% endif %}">
<a href="{% url 'edit_announce' announce.id %}">{{ announce.title }}</a>
<a href="{% url 'view_announce' pk=announce.id %}">{{ announce.title }}</a>
<div class="datetime">
{% if announce.publication_time %}
{% blocktrans with mtime=announce.publication_time|date:'DATETIME_FORMAT' %}

View File

@ -0,0 +1,51 @@
{% extends "corbo/announce_list.html" %}
{% load i18n %}
{% block breadcrumb %}
{{ block.super }}
<a href='{% url "view_category" slug=object.category.slug %}'>{{ object.category }}</a>
{% endblock %}
{% block appbar %}
<h2>{{ object.title }}</h2>
<a href="{% url 'delete_announce' pk=object.pk %}" rel="popup">{% trans 'Delete' %}</a>
<a href="{% url 'edit_announce' pk=object.pk %}">{% trans 'Edit' %}</a>
{% endblock %}
{% block content %}
<div class="announce_block">
<div class="announce_preview">
{{ object.text|safe }}
</div>
{% if object.publication_time or object.expiration_time or broadcasts %}
<div class="announce_dashboard">
{% if object.publication_time %}
<p>
<strong>{% trans "Publication" %}</strong>
{{ announce.publication_time|date:'DATETIME_FORMAT' }}
</p>
{% endif %}
{% if object.expiration_time %}
<p>
<strong>{% trans "Expiration" %}</strong>
{{ announce.expiration_time|date:'DATETIME_FORMAT' }}
</p>
{% endif %}
{% if broadcasts %}
{% for broadcast in broadcasts %}
<p>
<strong>{% trans "Sent" %}</strong>
{{ broadcast.deliver_time|date:'DATETIME_FORMAT' }}
{% blocktrans count delivers=broadcast.delivery_count %}
to {{ delivers }} destination
{% plural %}
to {{ delivers }} destinations
{% endblocktrans %}
</p>
{% endfor %}
{% endif %}
</div>
{% endif %}
</div>
{% endblock %}

View File

@ -87,7 +87,7 @@ class AnnounceEditView(UpdateView):
return context
def get_success_url(self):
return reverse('view_category', kwargs={'slug': self.object.category.slug})
return reverse('view_announce', kwargs={'pk': self.object.pk})
edit_announce = AnnounceEditView.as_view()
@ -255,6 +255,19 @@ class SubscriptionsImportView(FormView):
subscriptions_import = SubscriptionsImportView.as_view()
class AnnounceView(DetailView):
model = models.Announce
template_name = 'corbo/announce_view.html'
def get_context_data(self, **kwargs):
context = super(AnnounceView, self).get_context_data(**kwargs)
context['category'] = self.object.category
context['broadcasts'] = self.object.broadcast_set.filter(deliver_time__isnull=False)
return context
view_announce = AnnounceView.as_view()
def menu_json(request):
label = _('Announces')
json_str = json.dumps([{'label': force_text(label),

View File

@ -49,7 +49,7 @@ def test_emailing_with_no_subscriptions(app, categories, announces, mailoutbox):
for announce in announces:
broadcast = Broadcast.objects.get(announce=announce)
broadcast.send()
assert not broadcast.result
assert not broadcast.delivery_count
assert not len(mailoutbox)
@ -61,7 +61,7 @@ def test_send_email(app, categories, announces, mailoutbox):
for i, announce in enumerate(announces):
broadcast = Broadcast.objects.get(announce=announce)
broadcast.send()
assert broadcast.result
assert broadcast.delivery_count
assert len(mailoutbox) == i+1
@ -75,9 +75,9 @@ def test_check_inline_css(app, categories, announces, mailoutbox):
identifier='%s@example.net' % uuid, uuid=uuid)
broadcast = Broadcast.objects.get(announce=announce)
broadcast.send()
assert broadcast.result
assert len(mailoutbox) == total_sent + broadcast.result
total_sent += broadcast.result
assert broadcast.delivery_count
assert len(mailoutbox) == total_sent + broadcast.delivery_count
total_sent += broadcast.delivery_count
assert 'h2 style="color:#F00"' in mailoutbox[i].html
@ -100,14 +100,14 @@ def test_check_inline_images(mocked_get, app, categories, announces, mailoutbox)
headers={'content-type': 'image/png'},
content=storage.open(image_name).read())
broadcast.send()
assert broadcast.result
assert broadcast.delivery_count
assert len(mailoutbox) == total_sent + broadcast.result
assert len(mailoutbox) == total_sent + broadcast.delivery_count
attachments = [a['filename'] for a in mailoutbox[0].attachments.as_dict()]
assert image_name in attachments
assert 'cid:%s' % image_name in mail.outbox[0].html_body
assert 'cid:%s' % image_name in mail.outbox[0].text_body
total_sent += broadcast.result
total_sent += broadcast.delivery_count
storage.delete(image_name)
@ -123,7 +123,7 @@ def test_unsubscription_link(app, categories, announces, mailoutbox):
continue
broadcast = Broadcast.objects.get(announce=announce)
broadcast.send()
assert broadcast.result
assert broadcast.delivery_count
assert len(mailoutbox) == i+1
signature = urllib.unquote(re.findall('/unsubscribe/(.*)"', mailoutbox[i].html)[0])

View File

@ -4,6 +4,8 @@ import pytest
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User
from corbo.models import Broadcast
pytestmark = pytest.mark.django_db
@pytest.fixture
@ -142,12 +144,36 @@ def test_edit_announce(app, admin_user):
assert resp.location == 'http://testserver/manage/category/alerts/'
resp = app.get(resp.location)
assert 'First announce' in resp.content
announce_edit_page = resp.click('First announce')
announce_page = resp.click('First announce')
assert 'First announce' in announce_page.content
assert 'Edit' in announce_page.content
assert 'Delete' in announce_page.content
announce_edit_page = announce_page.click('Edit')
edit_form = announce_edit_page.forms[0]
edit_form['publication_time'] = '2017-03-03 09:00:00'
edit_form['expiration_time'] = '2017-12-31 23:00:00'
resp = edit_form.submit()
assert resp.status_int == 302
assert resp.location == 'http://testserver/manage/category/alerts/'
assert resp.location == 'http://testserver/manage/announce/1/'
# simulate announce deliver
broadcast = Broadcast.objects.get(announce__pk=1)
broadcast.deliver_time = '2017-03-30 20:00:00'
broadcast.delivery_count = 1
broadcast.save()
resp = app.get(resp.location)
assert 'Publication at March 3, 2017, 9 a.m.' in resp.content
assert 'Expiration at Dec. 31, 2017, 11 p.m.' in resp.content
assert 'Sent at March 30, 2017, 8 p.m. to 1 destination' in resp.content
broadcast.delivery_count = 2
broadcast.save()
resp = app.get('http://testserver/manage/announce/1/')
assert 'Sent at March 30, 2017, 8 p.m. to 2 destinations' in resp.content
def test_delete_announce(app, admin_user):
app = login(app)