0001-add-back-office-subscription-management-14093.patch
corbo/manage_urls.py | ||
---|---|---|
3 | 3 |
from .views import add_announce, edit_announce, delete_announce, \ |
4 | 4 |
add_category, edit_category, view_category, delete_category, manage, \ |
5 | 5 |
subscriptions_import, view_announce, email_announce, sms_announce, \ |
6 |
menu_json |
|
6 |
menu_json, subscription_delete, subscription_search
|
|
7 | 7 | |
8 | 8 |
urlpatterns = patterns('', |
9 | 9 |
url(r'^$', manage, name='manage'), |
... | ... | |
29 | 29 |
name='delete_category'), |
30 | 30 |
url(r'^category/(?P<slug>[\w-]+)/import-subscriptions/$', subscriptions_import, |
31 | 31 |
name='subscriptions-import'), |
32 |
url(r'^subscription/delete/(?P<pk>[\w-]+)/$', subscription_delete, |
|
33 |
name='subscription-delete'), |
|
34 |
url(r'^subscriptions/search$', subscription_search, |
|
35 |
name='subscription-search'), |
|
32 | 36 |
url(r'^menu.json$', menu_json), |
33 | 37 |
) |
corbo/models.py | ||
---|---|---|
189 | 189 |
identifier = models.CharField(_('identifier'), max_length=128, blank=True, |
190 | 190 |
help_text=_('ex.: mailto, ...')) |
191 | 191 | |
192 |
def __unicode__(self): |
|
193 |
return '%s - %s - %s' % (self.uuid, self.identifier, self.category.name) |
|
194 | ||
192 | 195 |
def get_identifier_display(self): |
193 | 196 |
try: |
194 | 197 |
scheme, identifier = self.identifier.split(':') |
corbo/templates/corbo/manage.html | ||
---|---|---|
12 | 12 |
</ul> |
13 | 13 |
{% endif %} |
14 | 14 |
<a href="{% url 'add_category' %}" rel='popup'>{% trans 'New category' %}</a> |
15 |
<a href="{% url 'subscription-search' %}">{% trans 'Search' %}</a> |
|
15 | 16 |
{% endblock %} |
16 | 17 | |
17 | 18 |
{% block content %} |
corbo/templates/corbo/manager_delete.html | ||
---|---|---|
1 |
{% extends "corbo/manage.html" %} |
|
2 |
{% load i18n %} |
|
3 | ||
4 |
{% block appbar %} |
|
5 |
<h2>{{ view.model.get_verbose_name }}</h2> |
|
6 |
{% endblock %} |
|
7 | ||
8 |
{% block content %} |
|
9 |
<form method="post"> |
|
10 |
{% csrf_token %} |
|
11 |
<p>{% blocktrans %}Are you sure you want to delete this?{% endblocktrans %}</p> |
|
12 |
<div class="buttons"> |
|
13 |
<button class="delete-button">{% trans 'Delete' %}</button> |
|
14 |
<a class="cancel" href="{{ object.get_absolute_url }}">{% trans 'Cancel' %}</a> |
|
15 |
</div> |
|
16 |
</form> |
|
17 |
{% endblock %} |
corbo/templates/corbo/subscription_search.html | ||
---|---|---|
1 |
{% extends "corbo/base.html" %} |
|
2 |
{% load i18n %} |
|
3 | ||
4 |
{% block appbar %} |
|
5 |
<h2>{% trans 'Search' %}</h2> |
|
6 |
{% endblock %} |
|
7 | ||
8 |
{% block breadcrumb %} |
|
9 |
{{ block.super }} |
|
10 |
<a href="{% url 'subscription-search' %}">{% trans 'Search' %}</a> |
|
11 |
{% endblock %} |
|
12 | ||
13 |
{% block content %} |
|
14 | ||
15 |
<form action="{% url 'subscription-search' %}"> |
|
16 |
<p><input name="q" type="search" value="{{query}}" /> <button>{% trans 'Search' %}</button> </p> |
|
17 |
<span class="help_text"> {% trans "type an email of a phone number" %} </span> |
|
18 |
</form> |
|
19 | ||
20 |
{% if subscriptions %} |
|
21 |
<div class="subscriptions"> |
|
22 |
<ul class="objects-list single-links"> |
|
23 |
{% for subscription in subscriptions %} |
|
24 |
<li>{{ subscription.category.name}}<a class="delete" rel="popup" href="{% url 'subscription-delete' pk=subscription.pk %}">{% trans "delete" %}</a></li> |
|
25 |
{% endfor %} |
|
26 |
</ul> |
|
27 |
</div> |
|
28 |
{% endif %} |
|
29 | ||
30 |
{% endblock %} |
corbo/views.py | ||
---|---|---|
3 | 3 | |
4 | 4 |
from django.conf import settings |
5 | 5 |
from django.core import signing |
6 |
from django.db.models import Q |
|
6 | 7 |
from django.utils import timezone |
7 | 8 |
from django.core.urlresolvers import reverse |
8 | 9 |
from django.views.generic import CreateView, UpdateView, DeleteView, \ |
9 |
ListView, TemplateView, RedirectView, DetailView, FormView, RedirectView |
|
10 |
ListView, TemplateView, RedirectView, DetailView, FormView, RedirectView, \ |
|
11 |
View |
|
10 | 12 |
from django.contrib.syndication.views import Feed |
11 | 13 |
from django.shortcuts import resolve_url |
12 | 14 |
from django.utils.encoding import force_text |
... | ... | |
256 | 258 |
subscriptions_import = SubscriptionsImportView.as_view() |
257 | 259 | |
258 | 260 | |
261 |
class SubscriptionSearchView(TemplateView): |
|
262 | ||
263 |
template_name = 'corbo/subscription_search.html' |
|
264 | ||
265 |
def get_context_data(self, **kwargs): |
|
266 |
context = super(SubscriptionSearchView, self).get_context_data(**kwargs) |
|
267 |
query = self.request.GET.get('q', '').strip() |
|
268 |
context['query'] = query |
|
269 |
if not query: |
|
270 |
return context |
|
271 |
context['subscriptions'] = models.Subscription.objects.filter( |
|
272 |
Q(identifier='mailto:' + query) | Q(identifier='sms:' + query)) |
|
273 |
return context |
|
274 | ||
275 | ||
276 |
subscription_search = SubscriptionSearchView.as_view() |
|
277 | ||
278 | ||
279 |
class SubscriptionDeleteView(DeleteView): |
|
280 | ||
281 |
model = models.Subscription |
|
282 |
template_name = 'corbo/manager_delete.html' |
|
283 | ||
284 |
def get_success_url(self): |
|
285 |
return reverse('subscription-search') |
|
286 | ||
287 | ||
288 |
subscription_delete = SubscriptionDeleteView.as_view() |
|
289 | ||
290 | ||
259 | 291 |
class AnnounceView(DetailView): |
260 | 292 |
model = models.Announce |
261 | 293 |
template_name = 'corbo/announce_view.html' |
tests/test_manager.py | ||
---|---|---|
7 | 7 |
from django.contrib.auth.models import User |
8 | 8 |
from django.test import override_settings |
9 | 9 | |
10 |
from corbo.models import Broadcast |
|
10 |
from corbo.models import Broadcast, Subscription
|
|
11 | 11 | |
12 | 12 |
pytestmark = pytest.mark.django_db |
13 | 13 | |
... | ... | |
352 | 352 |
assert record.name == 'corbo.utils' |
353 | 353 |
assert record.levelno == logging.WARNING |
354 | 354 |
assert 'Invalid URL' in record.getMessage() |
355 | ||
356 | ||
357 |
@pytest.fixture(scope='function', params=['foo@example.net', '0304050607']) |
|
358 |
def search_identifier(request, subscriptions): |
|
359 |
return request.param |
|
360 | ||
361 | ||
362 |
def test_subscriptions_search(app, admin_user, search_identifier): |
|
363 |
app = login(app) |
|
364 |
resp = app.get('/manage/') |
|
365 |
resp = resp.click('Search') |
|
366 |
# empty search |
|
367 |
resp = resp.form.submit() |
|
368 |
assert resp.html.find('div', {'class': 'subscriptions'}) is None |
|
369 |
# unknow identifier |
|
370 |
resp.form['q'] = 'toto' |
|
371 |
resp = resp.form.submit() |
|
372 |
assert resp.html.find('div', {'class': 'subscriptions'}) is None |
|
373 |
# search by email |
|
374 |
Subscription.objects.filter(identifier__contains=search_identifier).count() == 2 |
|
375 |
resp.form['q'] = search_identifier |
|
376 |
resp = resp.form.submit() |
|
377 |
assert len(resp.html.find('div', {'class': 'subscriptions'}).find_all('li')) == 2 |
|
378 |
# delete sub |
|
379 |
first_sub = Subscription.objects.filter(identifier__contains=search_identifier).first() |
|
380 |
resp = resp.click(href='/manage/subscription/delete/%d/' % first_sub.pk) |
|
381 |
resp = resp.form.submit().follow() |
|
382 |
Subscription.objects.filter(identifier=search_identifier).count() == 1 |
|
355 |
- |