Pro-everything
parent
806c09495a
commit
b7afdcc48b
|
@ -4,7 +4,7 @@ from accounts.models import UserProfile
|
|||
|
||||
|
||||
class UserProfileAdmin(admin.ModelAdmin):
|
||||
list_display = ('user', 'is_pro',)
|
||||
list_display = ('user', 'is_pro', 'stripe_id',)
|
||||
search_fields = ('user__username',)
|
||||
|
||||
admin.site.register(UserProfile, UserProfileAdmin)
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Adding field 'UserProfile.stripe_id'
|
||||
db.add_column('accounts_userprofile', 'stripe_id',
|
||||
self.gf('django.db.models.fields.IntegerField')(null=True, blank=True),
|
||||
keep_default=False)
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Deleting field 'UserProfile.stripe_id'
|
||||
db.delete_column('accounts_userprofile', 'stripe_id')
|
||||
|
||||
|
||||
models = {
|
||||
'accounts.userprofile': {
|
||||
'Meta': {'object_name': 'UserProfile'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_pro': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'stripe_id': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'})
|
||||
},
|
||||
'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'auth.permission': {
|
||||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'auth.user': {
|
||||
'Meta': {'object_name': 'User'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||
},
|
||||
'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['accounts']
|
|
@ -0,0 +1,66 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
|
||||
# Changing field 'UserProfile.stripe_id'
|
||||
db.alter_column('accounts_userprofile', 'stripe_id', self.gf('django.db.models.fields.CharField')(max_length=100, null=True))
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
# Changing field 'UserProfile.stripe_id'
|
||||
db.alter_column('accounts_userprofile', 'stripe_id', self.gf('django.db.models.fields.IntegerField')(null=True))
|
||||
|
||||
models = {
|
||||
'accounts.userprofile': {
|
||||
'Meta': {'object_name': 'UserProfile'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_pro': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'stripe_id': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'})
|
||||
},
|
||||
'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
'auth.permission': {
|
||||
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
'auth.user': {
|
||||
'Meta': {'object_name': 'User'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
|
||||
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
|
||||
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
|
||||
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
|
||||
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
|
||||
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||
},
|
||||
'contenttypes.contenttype': {
|
||||
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['accounts']
|
|
@ -1,13 +1,10 @@
|
|||
from django.contrib.auth.models import User
|
||||
from django.db import models
|
||||
|
||||
import caching.base
|
||||
|
||||
|
||||
class UserProfile(caching.base.CachingMixin, models.Model):
|
||||
class UserProfile(models.Model):
|
||||
user = models.ForeignKey(User, unique=True)
|
||||
is_pro = models.BooleanField(default=False)
|
||||
|
||||
objects = caching.base.CachingManager()
|
||||
stripe_id = models.CharField(max_length=100, null=True, blank=True)
|
||||
|
||||
User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0])
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1282,6 +1282,26 @@ div.profile {
|
|||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
a.pro {
|
||||
background: #DFDFDF;
|
||||
color: #3299B7;
|
||||
clear: left;
|
||||
display: block;
|
||||
float: left;
|
||||
font: bold italic 11px $Helvetica;
|
||||
margin-top: 10px;
|
||||
padding: 5px 0;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
text-transform: uppercase;
|
||||
width: 100%;
|
||||
@include border-radius(3px);
|
||||
@include box-shadow(0, 0, 3px, #FFF);
|
||||
|
||||
&:hover {
|
||||
background: #D8D8D8;
|
||||
}
|
||||
}
|
||||
}
|
||||
div.empty-snipts {
|
||||
background: rgba(128, 128, 128, .08);
|
||||
|
@ -1750,6 +1770,33 @@ body.pro {
|
|||
}
|
||||
}
|
||||
}
|
||||
fieldset {
|
||||
position: relative;
|
||||
}
|
||||
div.payment-errors {
|
||||
display: none;
|
||||
}
|
||||
div.payment-loading {
|
||||
background: rgba(#F2F2F2, .6);
|
||||
display: none;
|
||||
height: 202px;
|
||||
position: absolute;
|
||||
top: 37px;
|
||||
width: 100%;
|
||||
|
||||
span {
|
||||
background: #FFF;
|
||||
border: 3px solid #3299B7;
|
||||
color: #666;
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
margin: 80px auto 0 auto;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
width: 120px;
|
||||
@include border-radius;
|
||||
}
|
||||
}
|
||||
div.stripe {
|
||||
color: #C2C2C2;
|
||||
font: bold 11px/15px $Helvetica;
|
||||
|
@ -1764,6 +1811,14 @@ body.pro {
|
|||
}
|
||||
}
|
||||
}
|
||||
&.form-horizontal {
|
||||
fieldset {
|
||||
padding-top: 18px;
|
||||
}
|
||||
div.form-actions {
|
||||
margin-top: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
body.tags {
|
||||
|
|
|
@ -134,12 +134,12 @@ url=url&&addSlash(url);if(typeof url==='undefined'){url='/api/private/snipt/';th
|
|||
return url||null;};Site.SiteView=Backbone.View.extend({el:'body',initialize:function(opts){this.$body=$(this.el);this.$html=$('html');this.$html_body=this.$body.add(this.$html);this.$aside_nav=$('aside.nav',this.$body);this.$aside_nav_ul=$('ul',this.$aside_nav);this.$search_form=$('form.search',this.$body);this.$search_query=$('input#search-query',this.$body);this.$search_page_query=$('input.search-query',this.$body);this.$search_queries=this.$search_query.add(this.$search_page_query);this.$snipts=$('section#snipts article.snipt',this.$body);this.$modals=$('div.modal',this.$snipts);this.$main_edit=$('section#main-edit');this.$main=$('section#main');this.$keyboard_shortcuts=$('#keyboard-shortcuts',this.$body);this.$amazon_ads=$('section.amazon',this.$main);this.keyboardShortcuts();this.inFieldLabels();if(this.$amazon_ads.length){this.initAmazonAds();}
|
||||
var SniptListView=Snipt.SniptListView;this.snipt_list=new SniptListView({'snipts':this.$snipts});var that=this;this.$body.click(function(){if(!window.ui_halted&&!window.from_modal&&window.$selected){window.$selected.trigger('deselect');}
|
||||
if(window.from_modal){window.from_modal=false;}
|
||||
that.$aside_nav.removeClass('open');});this.$aside_nav_ul.click(function(e){e.stopPropagation();});$search_queries=this.$search_queries;$search_queries.focus(function(){if(window.$selected){$selected.trigger('deselect');}});this.$body.on('click','a.close',function(){$(this).parent().parent().modal('hide');window.ui_halted=false;return false;});this.$keyboard_shortcuts.on('hidden',function(){window.ui_halted=false;});if(this.$body.hasClass('pro-signup')){var $form=$('form#pro-signup');var $submit=$('button[type="submit"]',$form);var $name=$('input#name');var $cardNumber=$('input#number');var $expMonth=$('select[name="exp-month"]');var $expYear=$('select[name="exp-year"]');var $cvc=$('input#cvc');$form.submit(function(){$submit.attr('disabled','disabled');var errors=false;if(!Stripe.validateCardNumber($cardNumber.val())){$cardNumber.parents('div.control-group').addClass('error');errors=true;}else{$cardNumber.parents('div.control-group').removeClass('error');}
|
||||
that.$aside_nav.removeClass('open');});this.$aside_nav_ul.click(function(e){e.stopPropagation();});$search_queries=this.$search_queries;$search_queries.focus(function(){if(window.$selected){$selected.trigger('deselect');}});this.$body.on('click','a.close',function(){$(this).parent().parent().modal('hide');window.ui_halted=false;return false;});this.$keyboard_shortcuts.on('hidden',function(){window.ui_halted=false;});if(this.$body.hasClass('pro-signup')){var $form=$('form#pro-signup');var $submit=$('button[type="submit"]',$form);var $name=$('input#name');var $cardNumber=$('input#number');var $expMonth=$('select#exp-month');var $expYear=$('select#exp-year');var $cvc=$('input#cvc');$form.submit(function(){$submit.attr('disabled','disabled');var errors=false;if(!Stripe.validateCardNumber($cardNumber.val())){$cardNumber.parents('div.control-group').addClass('error');errors=true;}else{$cardNumber.parents('div.control-group').removeClass('error');}
|
||||
if(!Stripe.validateExpiry($expMonth.val(),$expYear.val())){$expMonth.parents('div.control-group').addClass('error');errors=true;}else{$expMonth.parents('div.control-group').removeClass('error');}
|
||||
if(!Stripe.validateCVC($cvc.val())){$cvc.parents('div.control-group').addClass('error');errors=true;}else{$cvc.parents('div.control-group').removeClass('error');}
|
||||
if(!errors){Stripe.createToken({name:$name.val(),number:$cardNumber.val(),cvc:$cvc.val(),exp_month:$expMonth.val(),exp_year:$expYear.val()},that.stripeResponseHandler);}else{$submit.removeAttr('disabled');}
|
||||
if(!errors){$('.payment-errors').hide();$('.payment-loading').show();Stripe.createToken({name:$name.val(),number:$cardNumber.val(),cvc:$cvc.val(),exp_month:$expMonth.val(),exp_year:$expYear.val()},that.stripeResponseHandler);}else{$submit.removeAttr('disabled');}
|
||||
return false;});}
|
||||
window.ui_halted=false;},events:{'showKeyboardShortcuts':'showKeyboardShortcuts','click a.mini-profile':'toggleMiniProfile'},keyboardShortcuts:function(){var $body=this.$body;var that=this;$search_queries=this.$search_queries;$search_page_query=this.$search_page_query;$search_query=this.$search_query;$document=$(document);$document.bind('keydown','/',function(e){if(!window.ui_halted){e.preventDefault();if($body.hasClass('search')){$search_page_query.focus();}else{$search_query.focus();}}});$document.bind('keydown','h',function(e){if(!window.ui_halted){window.ui_halted=true;$body.trigger('showKeyboardShortcuts');}else{if(that.$keyboard_shortcuts.is(':visible')){that.$keyboard_shortcuts.modal('hide');}}});$document.bind('keydown','t',function(e){if(!window.ui_halted){window.open('','_blank');}});$document.bind('keydown','r',function(e){if(!window.ui_halted){location.reload(true);}});$document.bind('keydown','Ctrl+h',function(e){if(!window.ui_halted){history.go(-1);}});$document.bind('keydown','Ctrl+l',function(e){if(!window.ui_halted){history.go(1);}});this.$search_queries.bind('keydown','esc',function(e){if(!window.ui_halted){e.preventDefault();this.blur();}});},showKeyboardShortcuts:function(){this.$keyboard_shortcuts.modal('toggle');},toggleMiniProfile:function(e){this.$aside_nav.toggleClass('open');return false;},inFieldLabels:function(){$('div.infield label',this.$body).inFieldLabels({fadeDuration:200});},stripeResponseHandler:function(status,response){console.log(status);console.log(response);if(response.error){}else{}},initAmazonAds:function(){var $more=$('div.more',this.$amazon_ads);var that=this;var adTemplate=$('script#amazon-ad').html();$('a',$more).on('click',function(){var $current=$('li:visible',that.$amazon_ads);$('li',that.$amazon_ads).hide();if($(this).hasClass('see-previous')){var $prev=$current.prev();if($prev.length){$prev=$prev;}else{$prev=$('li',that.$amazon_ads).eq(-1);}
|
||||
window.ui_halted=false;},events:{'showKeyboardShortcuts':'showKeyboardShortcuts','click a.mini-profile':'toggleMiniProfile'},keyboardShortcuts:function(){var $body=this.$body;var that=this;$search_queries=this.$search_queries;$search_page_query=this.$search_page_query;$search_query=this.$search_query;$document=$(document);$document.bind('keydown','/',function(e){if(!window.ui_halted){e.preventDefault();if($body.hasClass('search')){$search_page_query.focus();}else{$search_query.focus();}}});$document.bind('keydown','h',function(e){if(!window.ui_halted){window.ui_halted=true;$body.trigger('showKeyboardShortcuts');}else{if(that.$keyboard_shortcuts.is(':visible')){that.$keyboard_shortcuts.modal('hide');}}});$document.bind('keydown','t',function(e){if(!window.ui_halted){window.open('','_blank');}});$document.bind('keydown','r',function(e){if(!window.ui_halted){location.reload(true);}});$document.bind('keydown','Ctrl+h',function(e){if(!window.ui_halted){history.go(-1);}});$document.bind('keydown','Ctrl+l',function(e){if(!window.ui_halted){history.go(1);}});this.$search_queries.bind('keydown','esc',function(e){if(!window.ui_halted){e.preventDefault();this.blur();}});},showKeyboardShortcuts:function(){this.$keyboard_shortcuts.modal('toggle');},toggleMiniProfile:function(e){this.$aside_nav.toggleClass('open');return false;},inFieldLabels:function(){$('div.infield label',this.$body).inFieldLabels({fadeDuration:200});},stripeResponseHandler:function(status,response){var $form=$('form#pro-signup');if(response.error){$('button[type="submit"]',$form).removeAttr('disabled');$('.payment-loading').hide();$('.payment-errors').text(response.error.message).show();}else{var token=response.id;$('input#name').val('');$('input#number').val('');$('select#exp-month').val('');$('select#exp-year').val('');$('input#cvc').val('');$form.append("<input type='hidden' name='token' value='"+token+"'/>");$form.get(0).submit();}},initAmazonAds:function(){var $more=$('div.more',this.$amazon_ads);var that=this;var adTemplate=$('script#amazon-ad').html();$('a',$more).on('click',function(){var $current=$('li:visible',that.$amazon_ads);$('li',that.$amazon_ads).hide();if($(this).hasClass('see-previous')){var $prev=$current.prev();if($prev.length){$prev=$prev;}else{$prev=$('li',that.$amazon_ads).eq(-1);}
|
||||
$prev.fadeIn('fast');}else{var $next=$current.next();if($next.length){$next=$next;}else{$next=$('li',that.$amazon_ads).eq(0);}
|
||||
$next.fadeIn('fast');}
|
||||
return false;});$.getJSON('/api/public/a/',{'q':window.tag},function(resp){if(resp.result.length===0){that.$amazon_ads.slideUp('fast');}else{var html='';for(var i=0;i<resp.result.length;i++){if(resp.result[i].image){html+=_.template(adTemplate,{url:resp.result[i].url,title:resp.result[i].title,review:resp.result[i].review,image:resp.result[i].image});}}
|
||||
|
|
|
@ -103,8 +103,8 @@
|
|||
|
||||
var $name = $('input#name');
|
||||
var $cardNumber = $('input#number');
|
||||
var $expMonth = $('select[name="exp-month"]');
|
||||
var $expYear = $('select[name="exp-year"]');
|
||||
var $expMonth = $('select#exp-month');
|
||||
var $expYear = $('select#exp-year');
|
||||
var $cvc = $('input#cvc');
|
||||
|
||||
$form.submit(function() {
|
||||
|
@ -135,6 +135,10 @@
|
|||
}
|
||||
|
||||
if (!errors) {
|
||||
|
||||
$('.payment-errors').hide();
|
||||
$('.payment-loading').show();
|
||||
|
||||
Stripe.createToken({
|
||||
name: $name.val(),
|
||||
number: $cardNumber.val(),
|
||||
|
@ -142,6 +146,7 @@
|
|||
exp_month: $expMonth.val(),
|
||||
exp_year: $expYear.val()
|
||||
}, that.stripeResponseHandler);
|
||||
|
||||
} else {
|
||||
$submit.removeAttr('disabled');
|
||||
}
|
||||
|
@ -227,19 +232,27 @@
|
|||
});
|
||||
},
|
||||
stripeResponseHandler: function(status, response) {
|
||||
console.log(status);
|
||||
console.log(response);
|
||||
|
||||
var $form = $('form#pro-signup');
|
||||
|
||||
if (response.error) {
|
||||
// show the errors on the form
|
||||
//$(".payment-errors").text(response.error.message);
|
||||
$('button[type="submit"]', $form).removeAttr('disabled');
|
||||
$('.payment-loading').hide();
|
||||
$('.payment-errors').text(response.error.message).show();
|
||||
} else {
|
||||
//var form$ = $("#payment-form");
|
||||
// token contains id, last4, and card type
|
||||
//var token = response['id'];
|
||||
// insert the token into the form so it gets submitted to the server
|
||||
//form$.append("<input type='hidden' name='stripeToken' value='" + token + "'/>");
|
||||
// and submit
|
||||
//form$.get(0).submit();
|
||||
var token = response.id;
|
||||
|
||||
// Kill all of the form details so none of it touches our server.
|
||||
// Note, this is unnecessary, because the inputs themselves do not
|
||||
// have a name attr, meaning they'll never get sent to begin with.
|
||||
$('input#name').val('');
|
||||
$('input#number').val('');
|
||||
$('select#exp-month').val('');
|
||||
$('select#exp-year').val('');
|
||||
$('input#cvc').val('');
|
||||
|
||||
$form.append("<input type='hidden' name='token' value='" + token + "'/>");
|
||||
$form.get(0).submit();
|
||||
}
|
||||
},
|
||||
initAmazonAds: function() {
|
||||
|
|
|
@ -4,12 +4,12 @@ url=url&&addSlash(url);if(typeof url==='undefined'){url='/api/private/snipt/';th
|
|||
return url||null;};Site.SiteView=Backbone.View.extend({el:'body',initialize:function(opts){this.$body=$(this.el);this.$html=$('html');this.$html_body=this.$body.add(this.$html);this.$aside_nav=$('aside.nav',this.$body);this.$aside_nav_ul=$('ul',this.$aside_nav);this.$search_form=$('form.search',this.$body);this.$search_query=$('input#search-query',this.$body);this.$search_page_query=$('input.search-query',this.$body);this.$search_queries=this.$search_query.add(this.$search_page_query);this.$snipts=$('section#snipts article.snipt',this.$body);this.$modals=$('div.modal',this.$snipts);this.$main_edit=$('section#main-edit');this.$main=$('section#main');this.$keyboard_shortcuts=$('#keyboard-shortcuts',this.$body);this.$amazon_ads=$('section.amazon',this.$main);this.keyboardShortcuts();this.inFieldLabels();if(this.$amazon_ads.length){this.initAmazonAds();}
|
||||
var SniptListView=Snipt.SniptListView;this.snipt_list=new SniptListView({'snipts':this.$snipts});var that=this;this.$body.click(function(){if(!window.ui_halted&&!window.from_modal&&window.$selected){window.$selected.trigger('deselect');}
|
||||
if(window.from_modal){window.from_modal=false;}
|
||||
that.$aside_nav.removeClass('open');});this.$aside_nav_ul.click(function(e){e.stopPropagation();});$search_queries=this.$search_queries;$search_queries.focus(function(){if(window.$selected){$selected.trigger('deselect');}});this.$body.on('click','a.close',function(){$(this).parent().parent().modal('hide');window.ui_halted=false;return false;});this.$keyboard_shortcuts.on('hidden',function(){window.ui_halted=false;});if(this.$body.hasClass('pro-signup')){var $form=$('form#pro-signup');var $submit=$('button[type="submit"]',$form);var $name=$('input#name');var $cardNumber=$('input#number');var $expMonth=$('select[name="exp-month"]');var $expYear=$('select[name="exp-year"]');var $cvc=$('input#cvc');$form.submit(function(){$submit.attr('disabled','disabled');var errors=false;if(!Stripe.validateCardNumber($cardNumber.val())){$cardNumber.parents('div.control-group').addClass('error');errors=true;}else{$cardNumber.parents('div.control-group').removeClass('error');}
|
||||
that.$aside_nav.removeClass('open');});this.$aside_nav_ul.click(function(e){e.stopPropagation();});$search_queries=this.$search_queries;$search_queries.focus(function(){if(window.$selected){$selected.trigger('deselect');}});this.$body.on('click','a.close',function(){$(this).parent().parent().modal('hide');window.ui_halted=false;return false;});this.$keyboard_shortcuts.on('hidden',function(){window.ui_halted=false;});if(this.$body.hasClass('pro-signup')){var $form=$('form#pro-signup');var $submit=$('button[type="submit"]',$form);var $name=$('input#name');var $cardNumber=$('input#number');var $expMonth=$('select#exp-month');var $expYear=$('select#exp-year');var $cvc=$('input#cvc');$form.submit(function(){$submit.attr('disabled','disabled');var errors=false;if(!Stripe.validateCardNumber($cardNumber.val())){$cardNumber.parents('div.control-group').addClass('error');errors=true;}else{$cardNumber.parents('div.control-group').removeClass('error');}
|
||||
if(!Stripe.validateExpiry($expMonth.val(),$expYear.val())){$expMonth.parents('div.control-group').addClass('error');errors=true;}else{$expMonth.parents('div.control-group').removeClass('error');}
|
||||
if(!Stripe.validateCVC($cvc.val())){$cvc.parents('div.control-group').addClass('error');errors=true;}else{$cvc.parents('div.control-group').removeClass('error');}
|
||||
if(!errors){Stripe.createToken({name:$name.val(),number:$cardNumber.val(),cvc:$cvc.val(),exp_month:$expMonth.val(),exp_year:$expYear.val()},that.stripeResponseHandler);}else{$submit.removeAttr('disabled');}
|
||||
if(!errors){$('.payment-errors').hide();$('.payment-loading').show();Stripe.createToken({name:$name.val(),number:$cardNumber.val(),cvc:$cvc.val(),exp_month:$expMonth.val(),exp_year:$expYear.val()},that.stripeResponseHandler);}else{$submit.removeAttr('disabled');}
|
||||
return false;});}
|
||||
window.ui_halted=false;},events:{'showKeyboardShortcuts':'showKeyboardShortcuts','click a.mini-profile':'toggleMiniProfile'},keyboardShortcuts:function(){var $body=this.$body;var that=this;$search_queries=this.$search_queries;$search_page_query=this.$search_page_query;$search_query=this.$search_query;$document=$(document);$document.bind('keydown','/',function(e){if(!window.ui_halted){e.preventDefault();if($body.hasClass('search')){$search_page_query.focus();}else{$search_query.focus();}}});$document.bind('keydown','h',function(e){if(!window.ui_halted){window.ui_halted=true;$body.trigger('showKeyboardShortcuts');}else{if(that.$keyboard_shortcuts.is(':visible')){that.$keyboard_shortcuts.modal('hide');}}});$document.bind('keydown','t',function(e){if(!window.ui_halted){window.open('','_blank');}});$document.bind('keydown','r',function(e){if(!window.ui_halted){location.reload(true);}});$document.bind('keydown','Ctrl+h',function(e){if(!window.ui_halted){history.go(-1);}});$document.bind('keydown','Ctrl+l',function(e){if(!window.ui_halted){history.go(1);}});this.$search_queries.bind('keydown','esc',function(e){if(!window.ui_halted){e.preventDefault();this.blur();}});},showKeyboardShortcuts:function(){this.$keyboard_shortcuts.modal('toggle');},toggleMiniProfile:function(e){this.$aside_nav.toggleClass('open');return false;},inFieldLabels:function(){$('div.infield label',this.$body).inFieldLabels({fadeDuration:200});},stripeResponseHandler:function(status,response){console.log(status);console.log(response);if(response.error){}else{}},initAmazonAds:function(){var $more=$('div.more',this.$amazon_ads);var that=this;var adTemplate=$('script#amazon-ad').html();$('a',$more).on('click',function(){var $current=$('li:visible',that.$amazon_ads);$('li',that.$amazon_ads).hide();if($(this).hasClass('see-previous')){var $prev=$current.prev();if($prev.length){$prev=$prev;}else{$prev=$('li',that.$amazon_ads).eq(-1);}
|
||||
window.ui_halted=false;},events:{'showKeyboardShortcuts':'showKeyboardShortcuts','click a.mini-profile':'toggleMiniProfile'},keyboardShortcuts:function(){var $body=this.$body;var that=this;$search_queries=this.$search_queries;$search_page_query=this.$search_page_query;$search_query=this.$search_query;$document=$(document);$document.bind('keydown','/',function(e){if(!window.ui_halted){e.preventDefault();if($body.hasClass('search')){$search_page_query.focus();}else{$search_query.focus();}}});$document.bind('keydown','h',function(e){if(!window.ui_halted){window.ui_halted=true;$body.trigger('showKeyboardShortcuts');}else{if(that.$keyboard_shortcuts.is(':visible')){that.$keyboard_shortcuts.modal('hide');}}});$document.bind('keydown','t',function(e){if(!window.ui_halted){window.open('','_blank');}});$document.bind('keydown','r',function(e){if(!window.ui_halted){location.reload(true);}});$document.bind('keydown','Ctrl+h',function(e){if(!window.ui_halted){history.go(-1);}});$document.bind('keydown','Ctrl+l',function(e){if(!window.ui_halted){history.go(1);}});this.$search_queries.bind('keydown','esc',function(e){if(!window.ui_halted){e.preventDefault();this.blur();}});},showKeyboardShortcuts:function(){this.$keyboard_shortcuts.modal('toggle');},toggleMiniProfile:function(e){this.$aside_nav.toggleClass('open');return false;},inFieldLabels:function(){$('div.infield label',this.$body).inFieldLabels({fadeDuration:200});},stripeResponseHandler:function(status,response){var $form=$('form#pro-signup');if(response.error){$('button[type="submit"]',$form).removeAttr('disabled');$('.payment-loading').hide();$('.payment-errors').text(response.error.message).show();}else{var token=response.id;$('input#name').val('');$('input#number').val('');$('select#exp-month').val('');$('select#exp-year').val('');$('input#cvc').val('');$form.append("<input type='hidden' name='token' value='"+token+"'/>");$form.get(0).submit();}},initAmazonAds:function(){var $more=$('div.more',this.$amazon_ads);var that=this;var adTemplate=$('script#amazon-ad').html();$('a',$more).on('click',function(){var $current=$('li:visible',that.$amazon_ads);$('li',that.$amazon_ads).hide();if($(this).hasClass('see-previous')){var $prev=$current.prev();if($prev.length){$prev=$prev;}else{$prev=$('li',that.$amazon_ads).eq(-1);}
|
||||
$prev.fadeIn('fast');}else{var $next=$current.next();if($next.length){$next=$next;}else{$next=$('li',that.$amazon_ads).eq(0);}
|
||||
$next.fadeIn('fast');}
|
||||
return false;});$.getJSON('/api/public/a/',{'q':window.tag},function(resp){if(resp.result.length===0){that.$amazon_ads.slideUp('fast');}else{var html='';for(var i=0;i<resp.result.length;i++){if(resp.result[i].image){html+=_.template(adTemplate,{url:resp.result[i].url,title:resp.result[i].title,review:resp.result[i].review,image:resp.result[i].image});}}
|
||||
|
|
|
@ -15,12 +15,10 @@ from snipts.utils import slugify_uniquely
|
|||
|
||||
import datetime, md5, re
|
||||
|
||||
import caching.base
|
||||
|
||||
|
||||
site = Site.objects.all()[0]
|
||||
|
||||
class Snipt(caching.base.CachingMixin, models.Model):
|
||||
class Snipt(models.Model):
|
||||
"""An individual Snipt."""
|
||||
|
||||
user = models.ForeignKey(User, blank=True, null=True)
|
||||
|
@ -44,8 +42,6 @@ class Snipt(caching.base.CachingMixin, models.Model):
|
|||
modified = models.DateTimeField(auto_now=True, editable=False)
|
||||
publish_date = models.DateTimeField(blank=True, null=True)
|
||||
|
||||
objects = caching.base.CachingManager()
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
|
||||
if not self.slug:
|
||||
|
@ -158,14 +154,12 @@ class Snipt(caching.base.CachingMixin, models.Model):
|
|||
else:
|
||||
return get_lexer_by_name(self.lexer).name
|
||||
|
||||
class Favorite(caching.base.CachingMixin, models.Model):
|
||||
class Favorite(models.Model):
|
||||
snipt = models.ForeignKey(Snipt)
|
||||
user = models.ForeignKey(User)
|
||||
|
||||
created = models.DateTimeField(auto_now_add=True, editable=False)
|
||||
modified = models.DateTimeField(auto_now=True, editable=False)
|
||||
|
||||
objects = caching.base.CachingManager()
|
||||
|
||||
def __unicode__(self):
|
||||
return u'{} favorited by {}'.format(self.snipt.title, self.user.username)
|
||||
|
|
|
@ -33,6 +33,9 @@
|
|||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if user.profile.is_pro %}
|
||||
<a class="pro" href="/pro/">Pro</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% include "snipts/tags-user.html" %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -165,7 +165,7 @@
|
|||
<div class="heading">
|
||||
<h1>{{ tag.name }}</h1>
|
||||
</div>
|
||||
<section class="amazon">
|
||||
<section class="amazon {% if request.user.is_authenticated %}{% if request.user.profile.is_pro %}hidden{% endif %}{% endif %}">
|
||||
<ul></ul>
|
||||
<div class="more group">
|
||||
<span></span>
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block page-title %}Sign up for Snipt Pro{% endblock %}
|
||||
|
||||
{% block body-class %}{{ block.super }} static pro pro-signup{% endblock %}
|
||||
|
||||
{% block breadcrumb %}
|
||||
<li><a href="/pro/">Snipt Pro</a></li>
|
||||
<li><span class="prompt">/</span> <a href="/pro/signup/">Sign up</a></li>
|
||||
<li><span class="prompt">/</span> <a href="#">Complete</a></li>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="static-box">
|
||||
<h2>Snipt <span class="pro">Pro</span> members</h2>
|
||||
<p><strong>Congratulations!</strong> You're now a Snipt Pro.</p>
|
||||
<p>You should <a target="blank" href="http://twitter.com/intent/tweet?text=I'm now a Snipt Pro. Are you? https://snipt.net/pro/">tell the world</a>. If you ever need anything at all, <a href="mailto:nick@snipt.net">email Nick</a> directly.</p>
|
||||
<p>We'll bill you again (for $19 USD) exactly one year from now. We'll give you a heads up.</p>
|
||||
<p>Also, you rock. :)</p>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
{% block js %}
|
||||
{{ block.super }}
|
||||
Stripe.setPublishableKey('pk_RUeu9JcZVSzIr9qsJAnYrNJntJ8Vd');
|
||||
Stripe.setPublishableKey('pk_dHS5OwimSS1q73HB1YejiNfw37eI3');
|
||||
{% endblock %}
|
||||
|
||||
{% block breadcrumb %}
|
||||
|
@ -24,19 +24,21 @@
|
|||
<img src="/static/images/stripe.png" alt="" />
|
||||
</a>
|
||||
<h2>Snipt <span class="pro">Pro</span> signup</h2>
|
||||
<form class="form-horizontal" id="pro-signup" method="post" action="">
|
||||
<form class="form-horizontal" id="pro-signup" method="post" action="/pro/signup/complete/">
|
||||
<fieldset>
|
||||
<div class="payment-loading"><span>Please wait…</span></div>
|
||||
<legend>$19 USD will be charged to your card annually. Also, you rock. Tell yourself that every year, too.</legend>
|
||||
<div class="payment-errors alert alert-error"></div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="name">Name on card:</label>
|
||||
<div class="controls">
|
||||
<input type="text" class="input-xlarge" id="name">
|
||||
<input type="text" class="input-xlarge" id="name" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="number">Card number:</label>
|
||||
<div class="controls cards">
|
||||
<input type="text" class="input-xlarge" id="number">
|
||||
<input type="text" class="input-xlarge" id="number" />
|
||||
<img src="/static/images/card-visa.png" alt="Visa" />
|
||||
<img src="/static/images/card-mastercard.png" alt="MasterCard" />
|
||||
<img src="/static/images/card-discover.png" alt="Discover" />
|
||||
|
@ -46,7 +48,7 @@
|
|||
<div class="control-group">
|
||||
<label class="control-label" for="exp-month">Expiration date:</label>
|
||||
<div class="controls">
|
||||
<select name="exp-month" class="span2 exp-month">
|
||||
<select id="exp-month" class="span2 exp-month">
|
||||
<option value="">----</option>
|
||||
<option value="01">01 - January</option>
|
||||
<option value="02">02 - February</option>
|
||||
|
@ -61,7 +63,7 @@
|
|||
<option value="11">11 - November</option>
|
||||
<option value="12">12 - December</option>
|
||||
</select>
|
||||
<select name="exp-year" class="span1">
|
||||
<select id="exp-year" class="span1">
|
||||
<option value="">----</option>
|
||||
<option value="2012">2012</option>
|
||||
<option value="2013">2013</option>
|
||||
|
@ -84,6 +86,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-success">Sign up</button>
|
||||
<div class="security">
|
||||
<a href="https://stripe.com/help/security">Secure</a> by default. Every page on Snipt is secured with HTTPS.
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<ul>
|
||||
<li>No advertisements.</li>
|
||||
<li>“Pro” badge throughout the site.</li>
|
||||
<li>You’re supporting current and future development. This stuff takes time and money.</li>
|
||||
<li>You’re <strong>supporting</strong> current and future development. This stuff takes time and money.</li>
|
||||
</ul>
|
||||
<h6>Planned Pro features (not in order):</h6>
|
||||
<ul>
|
||||
|
@ -25,8 +25,7 @@
|
|||
<li>Ability to theme your embedded snipts in a specific theme.</li>
|
||||
<li>Custom domain and premium (Pro-only) themes for your <a href="https://blog.snipt.net/announcing-the-sniptnet-blogging-platform/">Snipt blog</a>.</li>
|
||||
</ul>
|
||||
<h3>Pro accounts are opening soon… sit tight!</h3>
|
||||
<!--<h3>Pro accounts are $19/year.</h3>-->
|
||||
<!--<h4><a href="/pro/signup/" class="btn btn-large btn-success">Sign Up Now</a></h4>-->
|
||||
<h3>Pro accounts are just $19/year.</h3>
|
||||
<h4><a href="/pro/signup/" class="btn btn-large btn-success">Sign Up Now</a></h4>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
|
6
urls.py
6
urls.py
|
@ -1,4 +1,4 @@
|
|||
from views import amazon_search, amazon_image, lexers, pro_signup, sitemap, tags
|
||||
from views import amazon_search, amazon_image, lexers, pro_signup, sitemap, tags, pro_signup_complete
|
||||
from django.conf.urls.defaults import include, patterns, url
|
||||
from django.views.generic.simple import direct_to_template
|
||||
from registration.forms import RegistrationFormUniqueEmail
|
||||
|
@ -34,9 +34,11 @@ urlpatterns = patterns('',
|
|||
url(r'^robots.txt$', direct_to_template, {'template': 'robots.txt'}),
|
||||
url(r'^humans.txt$', direct_to_template, {'template': 'humans.txt'}),
|
||||
url(r'^sitemap.xml$', sitemap),
|
||||
url(r'^tags/$', tags),
|
||||
|
||||
url(r'^pro/$', direct_to_template, {'template': 'pro.html'}),
|
||||
url(r'^pro/signup/$', pro_signup),
|
||||
url(r'^tags/$', tags),
|
||||
url(r'^pro/signup/complete/$', pro_signup_complete),
|
||||
|
||||
url(r'^api/public/lexer/$', lexers),
|
||||
url(r'^api/public/a/$', amazon_search),
|
||||
|
|
27
views.py
27
views.py
|
@ -12,6 +12,8 @@ from taggit.models import Tag
|
|||
|
||||
import os, urllib
|
||||
|
||||
import stripe
|
||||
|
||||
|
||||
@ajax_request
|
||||
def amazon_search(request):
|
||||
|
@ -95,6 +97,31 @@ def pro_signup(request):
|
|||
return HttpResponseRedirect('/' + request.user.username + '/')
|
||||
return {}
|
||||
|
||||
@login_required
|
||||
@render_to('pro-signup-complete.html')
|
||||
def pro_signup_complete(request):
|
||||
|
||||
if request.method == 'POST':
|
||||
|
||||
token = request.POST['token']
|
||||
stripe.api_key = '5XchbRsWVbksTRWSX67kOdBnCf01DxSh'
|
||||
|
||||
customer = stripe.Customer.create(
|
||||
card = token,
|
||||
plan = 'snipt-pro',
|
||||
email = request.user.email
|
||||
)
|
||||
|
||||
profile = request.user.profile
|
||||
profile.is_pro = True
|
||||
profile.stripe_id = customer.id
|
||||
profile.save()
|
||||
|
||||
return {}
|
||||
|
||||
else:
|
||||
return HttpResponseBadRequest()
|
||||
|
||||
def sitemap(request):
|
||||
|
||||
tags = Tag.objects.filter(snipt__public=True)
|
||||
|
|
Loading…
Reference in New Issue