Merge branch 'master' of github.com:Gluejar/regluit into payment

pull/1/head
Raymond Yee 2012-04-19 10:56:53 -07:00
commit 7fc0ae7165
15 changed files with 129 additions and 111 deletions

View File

@ -8,6 +8,10 @@ from regluit import payment
from djcelery.admin import TaskState, WorkerState, TaskMonitor, WorkerMonitor, \ from djcelery.admin import TaskState, WorkerState, TaskMonitor, WorkerMonitor, \
IntervalSchedule, CrontabSchedule, PeriodicTask, PeriodicTaskAdmin IntervalSchedule, CrontabSchedule, PeriodicTask, PeriodicTaskAdmin
from notification.admin import NoticeTypeAdmin, NoticeSettingAdmin, NoticeAdmin
from notification.models import NoticeType, NoticeSetting, Notice, ObservedItem, NoticeQueueBatch
import pickle
class RegluitAdmin(AdminSite): class RegluitAdmin(AdminSite):
login_template = 'registration/login.html' login_template = 'registration/login.html'
@ -69,6 +73,15 @@ class PaymentResponseAdmin(ModelAdmin):
class ReceiverAdmin(ModelAdmin): class ReceiverAdmin(ModelAdmin):
ordering = ('email',) ordering = ('email',)
def notice_queue_batch_data(obj):
return pickle.loads(str(obj.pickled_data).decode("base64"))
notice_queue_batch_data.short_description = 'unpickled_data'
class NoticeQueueBatchAdmin(ModelAdmin):
# show the pickled data in a form humans can parse more easily
list_display = (notice_queue_batch_data,)
pass
admin_site = RegluitAdmin("Admin") admin_site = RegluitAdmin("Admin")
admin_site.register(models.User, UserAdmin) admin_site.register(models.User, UserAdmin)
@ -99,3 +112,12 @@ admin_site.register(WorkerState, WorkerMonitor)
admin_site.register(IntervalSchedule) admin_site.register(IntervalSchedule)
admin_site.register(CrontabSchedule) admin_site.register(CrontabSchedule)
admin_site.register(PeriodicTask, PeriodicTaskAdmin) admin_site.register(PeriodicTask, PeriodicTaskAdmin)
# add the django-notification admin panel
# https://github.com/jtauber/django-notification/blob/master/notification/admin.py
admin_site.register(NoticeQueueBatch, NoticeQueueBatchAdmin)
admin_site.register(NoticeType, NoticeTypeAdmin)
admin_site.register(NoticeSetting, NoticeSettingAdmin)
admin_site.register(Notice, NoticeAdmin)
admin_site.register(ObservedItem)

View File

@ -1,3 +1,10 @@
"""
a command that creates a given number of random tasks to test out celery
"""
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from regluit.core import tasks from regluit.core import tasks
from regluit.core.models import CeleryTask from regluit.core.models import CeleryTask
@ -11,6 +18,16 @@ class Command(BaseCommand):
args = "<num_tasks action>" args = "<num_tasks action>"
def handle(self, num_tasks, action, **options): def handle(self, num_tasks, action, **options):
"""
actions:
c: create num_tasks tasks
s: print state of existing tasks
d: delete all tasks
an integer: compute factorial of the integer -- can then follow up with s to find the state
"""
import django
django.db.transaction.enter_transaction_management()
if action == 'c': if action == 'c':
for i in xrange(int(num_tasks)): for i in xrange(int(num_tasks)):
n = random.randint(1,1000) n = random.randint(1,1000)
@ -41,4 +58,4 @@ class Command(BaseCommand):
ct.save() ct.save()
except Exception, e: except Exception, e:
print e print e
django.db.transaction.commit()

23
deploy/crontab_please.txt Normal file
View File

@ -0,0 +1,23 @@
# Edit this file to introduce tasks to be run by cron.
#
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
#
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').#
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
#
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
#
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
#
# m h dom mon dow command
* * * * * cd /opt/regluit; source /opt/regluit/ENV/bin/activate; /opt/regluit/ENV/bin/django-admin.py emit_notices --settings=regluit.settings.please > /opt/regluit/deploy/emit_notices.log 2>&1 ; touch /opt/regluit/deploy/last-cron

23
deploy/crontab_prod.txt Normal file
View File

@ -0,0 +1,23 @@
# Edit this file to introduce tasks to be run by cron.
#
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
#
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').#
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
#
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
#
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
#
# m h dom mon dow command
* * * * * /opt/regluit/deploy/emit_notices.sh

8
deploy/emit_notices.sh Normal file
View File

@ -0,0 +1,8 @@
#!/bin/bash
# run django-admin.py emit_notices
cd /opt/regluit
source /opt/regluit/ENV/bin/activate
/opt/regluit/ENV/bin/django-admin.py emit_notices --settings=regluit.settings.prod > /opt/regluit/deploy/emit_notices.log 2>&1
touch /opt/regluit/deploy/last-cron

View File

@ -9,4 +9,6 @@ django-admin.py collectstatic --noinput --settings regluit.settings.prod
sudo /etc/init.d/apache2 restart sudo /etc/init.d/apache2 restart
sudo /etc/init.d/celeryd restart sudo /etc/init.d/celeryd restart
sudo /etc/init.d/celerybeat restart sudo /etc/init.d/celerybeat restart
chmod +x deploy/emit_notices.sh
crontab deploy/crontab_prod.txt
touch /opt/regluit/deploy/last-update touch /opt/regluit/deploy/last-update

View File

@ -15,4 +15,5 @@ django-admin.py collectstatic --noinput --settings regluit.settings.please
sudo /etc/init.d/apache2 restart sudo /etc/init.d/apache2 restart
sudo /etc/init.d/celeryd restart sudo /etc/init.d/celeryd restart
sudo /etc/init.d/celerybeat restart sudo /etc/init.d/celerybeat restart
crontab deploy/crontab_please.txt
touch /opt/regluit/deploy/last-update touch /opt/regluit/deploy/last-update

View File

@ -42,6 +42,10 @@
<div class="jsmodule rounded"> <div class="jsmodule rounded">
<div class="jsmod-content"> <div class="jsmod-content">
{% if faqmenu == 'modify' %}
<p>You have pledged ${{preapproval_amount}}. If you would like to modify your pledge, please use the following form.</p>
{% endif %}
{% comment %} {% comment %}
Even there is a CampaignPledgeForm in frontend/forms.py , the "widget" for premium_id is implemented in HTML here for now. Even there is a CampaignPledgeForm in frontend/forms.py , the "widget" for premium_id is implemented in HTML here for now.
{% endcomment %} {% endcomment %}
@ -73,7 +77,7 @@
{% endfor %} {% endfor %}
</ul> </ul>
<input type="submit" value="Pledge" id="pledgesubmit" /> <input type="submit" {% if faqmenu == 'modify' %}value="Modify Pledge"{% else %}value="Pledge"{% endif %} id="pledgesubmit" />
</form> </form>
</div> </div>

View File

@ -32,7 +32,7 @@ we need the share options and also something like the home page slide show to gi
<h2 class="thank-you">Thank you!</h2> <h2 class="thank-you">Thank you!</h2>
<p class="pledge_complete">You're now ungluing <I>{{work.title}}</I>.</p> <p class="pledge_complete">You're now ungluing <a href="{% url work work.id %}">{{work.title}}</a>.</p>
<p class="pledge_complete">You can help even more by sharing this campaign with your friends:</p> <p class="pledge_complete">You can help even more by sharing this campaign with your friends:</p>
<div id="widgetcode">Copy/paste this into your site:<br /><textarea rows="7" cols="22">&lt;iframe src="https://{{request.META.HTTP_HOST}}/api/widget/{{work.first_isbn_13}}/" width="152" height="325" frameborder="0"&gt;&lt;/iframe&gt;</textarea></div> <div id="widgetcode">Copy/paste this into your site:<br /><textarea rows="7" cols="22">&lt;iframe src="https://{{request.META.HTTP_HOST}}/api/widget/{{work.first_isbn_13}}/" width="152" height="325" frameborder="0"&gt;&lt;/iframe&gt;</textarea></div>

View File

@ -1,97 +0,0 @@
{% extends "basepledge.html" %}
{% block title %}Pledge (Modify){% endblock %}
{% block extra_extra_head %}
<link type="text/css" rel="stylesheet" href="/static/css/campaign.css" />
<link type="text/css" rel="stylesheet" href="/static/css/pledge.css" />
{% endblock %}
{% block doccontent %}
<div style="height:10px";></div>
<div class="book-detail">
<div class="book-detail-img">
<a href="#"><img src="{{ work.cover_image_thumbnail }}" alt="{{ work.title }}" title="{{ work.title }}" width="131" height="192" /></a>
</div>
<div class="book-detail-info">
<h2 class="book-name">{{ work.title }}</h2>
<h3 class="book-author">{{ work.author }}</h3>
<h3 class="book-year">{{ work.publication_date }}</h3>
<div class="find-book">
<label>Find it here</label>
<div class="find-link">
<a class="find-google" href="{{ work.googlebooks_url }}"><img src="/static/images/supporter_icons/googlebooks_square.png" title="Find on Google Books" alt="Find on Google Books" /></a>
<a rel="nofollow" class="find-openlibrary" href="{% url work_openlibrary work.id %}"><img src="/static/images/supporter_icons/openlibrary_square.png" title="Find on OpenLibrary" alt="Find on OpenLibrary"></a>
{% if not request.user.is_anonymous %}
{% if request.user.profile.goodreads_user_link %}
<a rel="nofollow" class="find-goodreads" href="{% url work_goodreads work.id %}"><img src="/static/images/supporter_icons/goodreads_square.png" title="Find on GoodReads" alt="Find on GoodReads"></a>
{% endif %}
{% if request.user.profile.librarything_id %}
<a rel="nofollow" class="find-librarything" href="{% url work_librarything work.id %}"><img src="/static/images/supporter_icons/librarything_square.png" title="Find on LibraryThing" alt="Find on LibraryThing" /></a>
{% endif %}
{% endif %}
</div>
</div>
<div class="pledged-info">
<div class="pledged-group">
{{ work.last_campaign.supporters.count }} Ungluers have pledged ${{ work.last_campaign.current_total }}
</div>
<div class="status">
<img src="/static/images/images/icon-book-37by25-{{ work.percent_unglued }}.png" title="book list status" alt="book list status" />
</div>
</div>
</div>
</div>
<div class="jsmodule rounded pledge">
<div class="jsmod-content">
${{ work.last_campaign.target }} needed by<br />
{{ work.last_campaign.deadline }}
</div>
</div>
<div class="jsmodule rounded">
<div class="jsmod-content">
<p>You have pledged ${{preapproval_amount}}. If you would like to modify your pledge, please use the following form.</p>
{% comment %}
Even there is a CampaignPledgeForm in frontend/forms.py , the "widget" for premium_id is implemented in HTML here for now.
{% endcomment %}
<form method="POST" action="{% url pledge_modify work_id=work.id %}">
{% csrf_token %}
{{ form.non_field_errors }}
<div class="pledge_amount">{{ form.preapproval_amount.label_tag }}: {{ form.preapproval_amount.errors }}${{ form.preapproval_amount }}</div>
{% comment %}
not supported yet; don't display
{{ form.anonymous.label_tag }}: {{ form.anonymous.errors }}{{ form.anonymous }}
{% endcomment %}
<ul class="support menu">
{% for premium in premiums %}
<label for="{{premium.id}}">
<li class="{% if forloop.first %}first{% else %}{% if forloop.last %}last{% endif %}{% endif %}">
<input type="radio" name="premium_id" value="{{premium.id}}" {% ifequal form.premium_id.value premium.id %}checked="checked"{% endifequal %} />
<span class="menu-item-price">
${{ premium.amount }}
</span>
<span class="menu-item-desc">
{{ premium.description }}
</span>
</a></li></label>
{% endfor %}
</ul>
<input type="submit" value="Modify Pledge" id="pledgesubmit" />
</form>
</div>
{% endblock %}

View File

@ -103,7 +103,7 @@ $j(document).ready(function(){
</div> </div>
{% if status == 'ACTIVE' %} {% if status == 'ACTIVE' %}
{% if pledged %} {% if pledged %}
<div class="btn_support modify"><form action="{% url pledge_modify work_id=work.id %}" method="get"><input type="submit" value="Change Pledge" /></form></div> <div class="btn_support modify"><form action="{% url pledge_modify work_id=work.id %}" method="get"><input type="submit" value="Modify Pledge" /></form></div>
{% else %} {% else %}
<div class="btn_support"><form action="{% url pledge work_id=work.id %}" method="get"><input type="submit" value="Support" /></form></div> <div class="btn_support"><form action="{% url pledge work_id=work.id %}" method="get"><input type="submit" value="Support" /></form></div>
{% endif %} {% endif %}

View File

@ -479,7 +479,7 @@ class PledgeModifyView(FormView):
""" """
A view to handle request to change an existing pledge A view to handle request to change an existing pledge
""" """
template_name="pledge_modify.html" template_name="pledge.html"
form_class = CampaignPledgeForm form_class = CampaignPledgeForm
embedded = False embedded = False
@ -529,7 +529,7 @@ class PledgeModifyView(FormView):
form_class = self.get_form_class() form_class = self.get_form_class()
form = form_class(initial=data) form = form_class(initial=data)
context.update({'work':work,'campaign':campaign, 'premiums':premiums, 'form':form,'preapproval_amount':preapproval_amount, 'premium_id':premium_id, 'faqmenu': 'pledge'}) context.update({'work':work,'campaign':campaign, 'premiums':premiums, 'form':form,'preapproval_amount':preapproval_amount, 'premium_id':premium_id, 'faqmenu': 'modify'})
return context return context

View File

@ -570,7 +570,7 @@ h2.thank-you {
font-size: 34px; font-size: 34px;
color: #8dc63f; color: #8dc63f;
} }
.pledge_complete { .pledge_complete, .pledge_complete a {
font-size: 14px; font-size: 14px;
line-height: 17px; line-height: 17px;
margin-bottom: 14px; margin-bottom: 14px;
@ -579,7 +579,7 @@ h2.thank-you {
width: 960px !important; width: 960px !important;
} }
h3 .pledge_indent { h3 .pledge_indent {
margin-left: 215px; margin-left: 240px;
} }
ul.social.pledge { ul.social.pledge {
margin-bottom: 150px; margin-bottom: 150px;

View File

@ -294,7 +294,7 @@ h2.thank-you {
color: @call-to-action; color: @call-to-action;
} }
.pledge_complete { .pledge_complete, .pledge_complete a {
font-size: 14px; font-size: 14px;
line-height: 17px; line-height: 17px;
margin-bottom: 14px; margin-bottom: 14px;
@ -305,7 +305,7 @@ h2.thank-you {
} }
h3 .pledge_indent { h3 .pledge_indent {
margin-left: 215px; margin-left: 240px;
} }
ul.social.pledge { ul.social.pledge {

View File

@ -3,6 +3,10 @@ import boto
# connect up parts of the Amazon infrastructure # connect up parts of the Amazon infrastructure
# notes: to delete snapshots I have made of instances, one has to deregister the AMI first and then delete the snapshot
GLUEJAR_ACCOUNT_ID = 439256357102
ec2 = boto.connect_ec2() ec2 = boto.connect_ec2()
cw = boto.connect_cloudwatch() cw = boto.connect_cloudwatch()
rds = boto.connect_rds() rds = boto.connect_rds()
@ -18,12 +22,23 @@ def all_zones():
def all_rds(): def all_rds():
return rds.get_all_dbinstances() return rds.get_all_dbinstances()
def all_snapshots(owner=GLUEJAR_ACCOUNT_ID):
"""by default, return only snapshots owned by Gluejar -- None returns all snapshots available to us"""
return ec2.get_all_snapshots(owner=owner)
def instance(tag_name): def instance(tag_name):
try: try:
return ec2.get_all_instances(filters={'tag:Name' : tag_name})[0].instances[0] return ec2.get_all_instances(filters={'tag:Name' : tag_name})[0].instances[0]
except Exception, e: except Exception, e:
return None return None
def all_images(owners=(GLUEJAR_ACCOUNT_ID, )):
return ec2.get_all_images(owners=owners)
def stop_instances(instances):
return ec2.stop_instances(instance_ids=[instance.id for instance in instances])
def console_output(instance): def console_output(instance):
"""returnn console output of instance""" """returnn console output of instance"""
try: try: