Offer to subscribe / create classes if user zwrites to a non-subbed class

Here we check if a class exists. If not, we prompt the user to create, sub,
and send his message to the class. If the class exists but we're not subbed
we prompt the user to sub.

This commit also added a decorator to views.py and refactored out some
redundant code.

(imported from commit 7234ef6c080f2a6de6ff0922635dddd90032f7fe)
This commit is contained in:
Luke Faraone 2012-09-05 17:38:20 -04:00
parent 31ece4d3aa
commit f6b481546f
5 changed files with 80 additions and 12 deletions

View File

@ -19,7 +19,8 @@ urlpatterns = patterns('',
url(r'^subscriptions/manage/$', 'zephyr.views.manage_subscriptions', name='manage_subscriptions'), url(r'^subscriptions/manage/$', 'zephyr.views.manage_subscriptions', name='manage_subscriptions'),
url(r'^subscriptions/add/$', 'zephyr.views.add_subscriptions', name='add_subscriptions'), url(r'^subscriptions/add/$', 'zephyr.views.add_subscriptions', name='add_subscriptions'),
url(r'^static/(?P<path>.*)$', 'django.views.static.serve', url(r'^static/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': os.path.join(settings.SITE_ROOT, '..', 'zephyr', 'static/')}) {'document_root': os.path.join(settings.SITE_ROOT, '..', 'zephyr', 'static/')}),
url(r'^subscriptions/exists/(?P<zephyr_class>.*)$', 'zephyr.views.class_exists', name='class_exists'),
# Uncomment the admin/doc line below to enable admin documentation: # Uncomment the admin/doc line below to enable admin documentation:
# url(r'^admin/doc/', include('django.contrib.admindocs.urls')), # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),

View File

@ -51,6 +51,16 @@ var people_list = {{ people }};
</ul> </ul>
<div class="tab-content"> <div class="tab-content">
<div class="alert" id="class-dne">
<p>The class <span class="classname" id="class-dne-name"></span> does not exist.</p>
<a id="create-it" class="btn btn-primary" href="#">Create and send</a>
<a class="btn" onClick="$('#class-dne').stop(true).fadeOut(500);">Cancel message</a>
</div>
<div class="alert" id="class-nosub">
<p>You're not subscribed to the class <span class="classname" id="class-nosub-name"></span>.</p>
<a id="sub-it" class="btn btn-primary" href="#">Subscribe and send</a>
<a class="btn" onClick="$('#class-nosub').stop(true).fadeOut(500);">Cancel message</a>
</div>
<div class="tab-pane active" id="class-message"> <div class="tab-pane active" id="class-message">
<form action="/zephyr/" method="post" class="zephyr"> <form action="/zephyr/" method="post" class="zephyr">
<input type="hidden" name="type" value="class" /> <input type="hidden" name="type" value="class" />

View File

@ -42,6 +42,12 @@ $.ajaxSetup({
} }
}); });
function sub(zephyr_class) {
// Supports multiple classes, separate by commas.
// TODO: check the return value and handle an error condition
$.post('/subscriptions/add/', {new_subscriptions: zephyr_class});
}
$(function() { $(function() {
var status_classes = 'alert-error alert-success alert-info'; var status_classes = 'alert-error alert-success alert-info';
var send_status = $('#send-status'); var send_status = $('#send-status');
@ -56,6 +62,42 @@ $(function() {
.stop(true).fadeTo(0,1); .stop(true).fadeTo(0,1);
buttons.attr('disabled', 'disabled'); buttons.attr('disabled', 'disabled');
buttons.blur() buttons.blur()
var okay = true;
$.ajaxSetup({async:false}); // so we get blocking gets
$.get("subscriptions/exists/" + $("#class").val(), function(data) {
if (data == "False") {
// The class doesn't exist
okay = false;
send_status.removeClass(status_classes)
send_status.toggle();
$('#class-dne-name').text($("#class").val());
$('#class-dne').show();
$('#create-it').focus()
.click(function() {
sub($("#class").val());
$("#class-message form").ajaxSubmit();
$('#class-dne').stop(true).fadeOut(500);
});
buttons.removeAttr('disabled');
}
});
$.ajaxSetup({async:true});
if (okay && class_list.indexOf($("#class").val()) == -1) {
// You're not subbed to the class
okay = false;
send_status.removeClass(status_classes);
send_status.toggle();
$('#class-nosub-name').text($("#class").val());
$('#class-nosub').show();
$('#sub-it').focus()
.click(function() {
sub($("#class").val());
$("#class-message form").ajaxSubmit();
$('#class-nosub').stop(true).fadeOut(500);
});
buttons.removeAttr('disabled');
}
return okay;
}, },
success: function (resp, statusText, xhr, form) { success: function (resp, statusText, xhr, form) {
form.find('textarea').val(''); form.find('textarea').val('');

View File

@ -90,6 +90,18 @@ form.zephyr textarea {
display: none; display: none;
} }
#class-dne {
display: none;
}
#class-nosub {
display: none;
}
span.classname {
font-weight: bold;
}
#connection-error .alert { #connection-error .alert {
margin-bottom: auto; margin-bottom: auto;
} }

View File

@ -20,6 +20,13 @@ import datetime
import simplejson import simplejson
import socket import socket
def require_post(view_func):
def _wrapped_view_func(request, *args, **kwargs):
if request.method != "POST":
return HttpResponseBadRequest('This form can only be submitted by POST.')
return view_func(request, *args, **kwargs)
return _wrapped_view_func
def json_response(res_type="success", msg="", status=200): def json_response(res_type="success", msg="", status=200):
return HttpResponse(content=simplejson.dumps({"result":res_type, "msg":msg}), return HttpResponse(content=simplejson.dumps({"result":res_type, "msg":msg}),
mimetype='application/json', status=status) mimetype='application/json', status=status)
@ -95,10 +102,8 @@ def home(request):
context_instance=RequestContext(request)) context_instance=RequestContext(request))
@login_required @login_required
@require_post
def update(request): def update(request):
if not request.POST:
# Do something
pass
user = request.user user = request.user
user_profile = UserProfile.objects.get(user=user) user_profile = UserProfile.objects.get(user=user)
if request.POST.get('pointer'): if request.POST.get('pointer'):
@ -107,11 +112,8 @@ def update(request):
return json_success() return json_success()
@asynchronous @asynchronous
@require_post
def get_updates_longpoll(request, handler): def get_updates_longpoll(request, handler):
if not request.POST:
# TODO: Do something
pass
last_received = request.POST.get('last_received') last_received = request.POST.get('last_received')
if not last_received: if not last_received:
# TODO: return error? # TODO: return error?
@ -132,11 +134,8 @@ def get_updates_longpoll(request, handler):
user_profile.add_callback(handler.async_callback(on_receive), last_received) user_profile.add_callback(handler.async_callback(on_receive), last_received)
@login_required @login_required
@require_post
def zephyr(request): def zephyr(request):
if not request.POST:
# TODO: Do something
pass
user_profile = UserProfile.objects.get(user=request.user) user_profile = UserProfile.objects.get(user=request.user)
zephyr_type = request.POST["type"] zephyr_type = request.POST["type"]
if zephyr_type == 'class': if zephyr_type == 'class':
@ -262,3 +261,7 @@ def add_subscriptions(request):
new_subscription.save() new_subscription.save()
return HttpResponseRedirect(reverse('zephyr.views.subscriptions')) return HttpResponseRedirect(reverse('zephyr.views.subscriptions'))
@login_required
def class_exists(request, zephyr_class):
return HttpResponse(bool(ZephyrClass.objects.filter(name=zephyr_class)))