From 11d2a24f93c9576a8ad64e7e274b0fbd41c42a0e Mon Sep 17 00:00:00 2001 From: Eric Holscher Date: Mon, 14 Nov 2016 12:15:55 -0800 Subject: [PATCH 01/16] Add a way for sponsors to pay without asking for logos etc. --- readthedocs/donate/forms.py | 44 +++++++++ .../templates/donate/ethicalads-success.html | 15 +++ .../donate/templates/donate/ethicalads.html | 91 +++++++++++++++++++ readthedocs/donate/urls.py | 7 +- readthedocs/donate/views.py | 18 +++- 5 files changed, 171 insertions(+), 4 deletions(-) create mode 100644 readthedocs/donate/templates/donate/ethicalads-success.html create mode 100644 readthedocs/donate/templates/donate/ethicalads.html diff --git a/readthedocs/donate/forms.py b/readthedocs/donate/forms.py index 735a3c507a4..1289ae14e4d 100644 --- a/readthedocs/donate/forms.py +++ b/readthedocs/donate/forms.py @@ -86,3 +86,47 @@ def save(self, commit=True): supporter.user = self.user supporter.save() return supporter + + +class EthicalAdForm(StripeResourceMixin, StripeModelForm): + + """Payment form for ethical ads + + This extends the basic payment form, giving fields for credit card number, + expiry, and CVV. The proper Knockout data bindings are established on + :py:class:`StripeModelForm` + """ + + class Meta: + model = Supporter + fields = ( + 'last_4_digits', + 'name', + 'email', + 'dollars', + ) + help_texts = { + 'email': _('Your email is used so we can send you a receipt'), + } + widgets = { + 'dollars': forms.HiddenInput(attrs={ + 'data-bind': 'value: dollars' + }), + 'last_4_digits': forms.TextInput(attrs={ + 'data-bind': 'valueInit: card_digits, value: card_digits' + }), + } + + last_4_digits = forms.CharField(widget=forms.HiddenInput(), required=True) + name = forms.CharField(required=True) + email = forms.CharField(required=True) + + def validate_stripe(self): + """Call stripe for payment (not ideal here) and clean up logo < $200""" + stripe.Charge.create( + amount=int(self.cleaned_data['dollars']) * 100, + currency='usd', + source=self.cleaned_data['stripe_token'], + description='Read the Docs Ethical Ads', + receipt_email=self.cleaned_data['email'] + ) diff --git a/readthedocs/donate/templates/donate/ethicalads-success.html b/readthedocs/donate/templates/donate/ethicalads-success.html new file mode 100644 index 00000000000..25eb2e5a9fd --- /dev/null +++ b/readthedocs/donate/templates/donate/ethicalads-success.html @@ -0,0 +1,15 @@ +{% extends "base.html" %} + +{% load i18n %} +{% load static %} + +{% block title %}{% trans "Sustainability" %}{% endblock %} + +{% block content %} +

Thanks for your support

+ +

+ We appreciate your contribution greatly, thank you for showing your support! + Your help will go a long ways towards making the service more sustainable. +

+{% endblock %} diff --git a/readthedocs/donate/templates/donate/ethicalads.html b/readthedocs/donate/templates/donate/ethicalads.html new file mode 100644 index 00000000000..03c59a60060 --- /dev/null +++ b/readthedocs/donate/templates/donate/ethicalads.html @@ -0,0 +1,91 @@ +{% extends "base.html" %} + +{% load i18n %} +{% load static %} + +{% block title %}{% trans "Pay for your ad" %}{% endblock %} + +{% block extra_links %} + +{% endblock %} + +{% block extra_scripts %} + + + + +{% endblock %} + + +{% block content %} +

Pay for your Sponsorship

+ +

+ This form can be used to pay for your sponsorship of Read the Docs. + Thanks for helping make Open Source more sustainable! +

+ + +{% endblock %} diff --git a/readthedocs/donate/urls.py b/readthedocs/donate/urls.py index 6b6beb3e665..f151b73c868 100644 --- a/readthedocs/donate/urls.py +++ b/readthedocs/donate/urls.py @@ -1,13 +1,14 @@ from django.conf.urls import url, include -from .views import DonateCreateView -from .views import DonateListView -from .views import DonateSuccessView +from .views import DonateCreateView, DonateListView, DonateSuccessView +from .views import PayAdsView, PaySuccess from .views import click_proxy, view_proxy urlpatterns = [ url(r'^$', DonateListView.as_view(), name='donate'), + url(r'^pay/$', PayAdsView.as_view(), name='pay_ads'), + url(r'^pay/success/$', PaySuccess.as_view(), name='pay_ads'), url(r'^contribute/$', DonateCreateView.as_view(), name='donate_add'), url(r'^contribute/thanks$', DonateSuccessView.as_view(), name='donate_success'), url(r'^view/(?P\d+)/(?P.+)/$', view_proxy, name='donate_view_proxy'), diff --git a/readthedocs/donate/views.py b/readthedocs/donate/views.py index fa132530847..dd6e33a1bf0 100644 --- a/readthedocs/donate/views.py +++ b/readthedocs/donate/views.py @@ -15,12 +15,28 @@ from readthedocs.projects.models import Project from .models import Supporter, SupporterPromo, CLICKS, VIEWS -from .forms import SupporterForm +from .forms import SupporterForm, EthicalAdForm from .mixins import DonateProgressMixin log = logging.getLogger(__name__) +class PayAdsView(StripeMixin, CreateView): + + """Create a donation locally and in Stripe""" + + form_class = EthicalAdForm + success_message = _('Your payment has been received') + template_name = 'donate/ethicalads.html' + + def get_success_url(self): + return reverse('pay_success') + + +class PaySuccess(TemplateView): + template_name = 'donate/ethicalads-success.html' + + class DonateCreateView(StripeMixin, CreateView): """Create a donation locally and in Stripe""" From 047bfa67375ef5717874df0e8fdf900b9c99d63d Mon Sep 17 00:00:00 2001 From: Eric Holscher Date: Mon, 14 Nov 2016 12:16:55 -0800 Subject: [PATCH 02/16] Fix URL name --- readthedocs/donate/urls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readthedocs/donate/urls.py b/readthedocs/donate/urls.py index f151b73c868..65f4009a7a6 100644 --- a/readthedocs/donate/urls.py +++ b/readthedocs/donate/urls.py @@ -8,7 +8,7 @@ urlpatterns = [ url(r'^$', DonateListView.as_view(), name='donate'), url(r'^pay/$', PayAdsView.as_view(), name='pay_ads'), - url(r'^pay/success/$', PaySuccess.as_view(), name='pay_ads'), + url(r'^pay/success/$', PaySuccess.as_view(), name='pay_success'), url(r'^contribute/$', DonateCreateView.as_view(), name='donate_add'), url(r'^contribute/thanks$', DonateSuccessView.as_view(), name='donate_success'), url(r'^view/(?P\d+)/(?P.+)/$', view_proxy, name='donate_view_proxy'), From fe9577eb3f692db7d12ba6bf17e2e4253e8d6ae2 Mon Sep 17 00:00:00 2001 From: Eric Holscher Date: Wed, 16 Nov 2016 11:06:05 -0800 Subject: [PATCH 03/16] Add ability to see latest promo details. --- .../donate/templates/donate/promo_detail.html | 37 +++++++++++++++++++ readthedocs/donate/urls.py | 3 +- readthedocs/donate/views.py | 8 ++++ 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 readthedocs/donate/templates/donate/promo_detail.html diff --git a/readthedocs/donate/templates/donate/promo_detail.html b/readthedocs/donate/templates/donate/promo_detail.html new file mode 100644 index 00000000000..4480ac69b03 --- /dev/null +++ b/readthedocs/donate/templates/donate/promo_detail.html @@ -0,0 +1,37 @@ +{% extends "base.html" %} + +{% load i18n %} +{% load static %} + +{% block title %}{% trans "Promo Detail" %}{% endblock %} + +{% block content %} + +

Promo Results

+ +{% for promo in promos %} + +

+Results for {{ promo.name }} +

+ + + + + + + + + {% for day in promo.impressions.all %} + + + + + + + {% endfor %} +
Day (UTC)ViewsClicksCTR
{{ day.date }}{{ day.views }}{{ day.clicks }}{{ day.click_ratio }}%
+ +{% endfor %} + +{% endblock %} diff --git a/readthedocs/donate/urls.py b/readthedocs/donate/urls.py index 65f4009a7a6..210bb56df5c 100644 --- a/readthedocs/donate/urls.py +++ b/readthedocs/donate/urls.py @@ -1,7 +1,7 @@ from django.conf.urls import url, include from .views import DonateCreateView, DonateListView, DonateSuccessView -from .views import PayAdsView, PaySuccess +from .views import PayAdsView, PaySuccess, PromoDetailView from .views import click_proxy, view_proxy @@ -9,6 +9,7 @@ url(r'^$', DonateListView.as_view(), name='donate'), url(r'^pay/$', PayAdsView.as_view(), name='pay_ads'), url(r'^pay/success/$', PaySuccess.as_view(), name='pay_success'), + url(r'^report/(?P.+)/$', PromoDetailView.as_view(), name='donate_promo_detail'), url(r'^contribute/$', DonateCreateView.as_view(), name='donate_add'), url(r'^contribute/thanks$', DonateSuccessView.as_view(), name='donate_success'), url(r'^view/(?P\d+)/(?P.+)/$', view_proxy, name='donate_view_proxy'), diff --git a/readthedocs/donate/views.py b/readthedocs/donate/views.py index dd6e33a1bf0..287c360b97a 100644 --- a/readthedocs/donate/views.py +++ b/readthedocs/donate/views.py @@ -77,6 +77,14 @@ def get_template_names(self): return [self.template_name] +class PromoDetailView(TemplateView): + template_name = 'donate/promo_detail.html' + + def get_context_data(self, promo_slug): + slugs = promo_slug.split(',') + return {'promos': SupporterPromo.objects.filter(analytics_id__in=slugs)} + + def click_proxy(request, promo_id, hash): promo = get_object_or_404(SupporterPromo, pk=promo_id) count = cache.get(promo.cache_key(type=CLICKS, hash=hash), None) From 333371e4bbd2d218e376c1c028e43394b4192df1 Mon Sep 17 00:00:00 2001 From: Eric Holscher Date: Wed, 16 Nov 2016 11:10:24 -0800 Subject: [PATCH 04/16] Fix review feedback. --- readthedocs/donate/forms.py | 3 +-- readthedocs/donate/templates/donate/ethicalads-success.html | 6 +++--- readthedocs/donate/templates/donate/ethicalads.html | 3 ++- readthedocs/donate/views.py | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/readthedocs/donate/forms.py b/readthedocs/donate/forms.py index 1289ae14e4d..d9a90a5af3f 100644 --- a/readthedocs/donate/forms.py +++ b/readthedocs/donate/forms.py @@ -122,11 +122,10 @@ class Meta: email = forms.CharField(required=True) def validate_stripe(self): - """Call stripe for payment (not ideal here) and clean up logo < $200""" stripe.Charge.create( amount=int(self.cleaned_data['dollars']) * 100, currency='usd', source=self.cleaned_data['stripe_token'], - description='Read the Docs Ethical Ads', + description='Read the Docs Sponsorship Payment', receipt_email=self.cleaned_data['email'] ) diff --git a/readthedocs/donate/templates/donate/ethicalads-success.html b/readthedocs/donate/templates/donate/ethicalads-success.html index 25eb2e5a9fd..caf2f7a7b3b 100644 --- a/readthedocs/donate/templates/donate/ethicalads-success.html +++ b/readthedocs/donate/templates/donate/ethicalads-success.html @@ -3,13 +3,13 @@ {% load i18n %} {% load static %} -{% block title %}{% trans "Sustainability" %}{% endblock %} +{% block title %}{% trans "Sponsorship" %}{% endblock %} {% block content %}

Thanks for your support

- We appreciate your contribution greatly, thank you for showing your support! - Your help will go a long ways towards making the service more sustainable. + We think that our Ethical Advertising campaign is a wonderful step forward for running ads on open source projects. + Thanks for your support.

{% endblock %} diff --git a/readthedocs/donate/templates/donate/ethicalads.html b/readthedocs/donate/templates/donate/ethicalads.html index 03c59a60060..64cbe75f537 100644 --- a/readthedocs/donate/templates/donate/ethicalads.html +++ b/readthedocs/donate/templates/donate/ethicalads.html @@ -35,7 +35,8 @@

Pay for your Sponsorship

This form can be used to pay for your sponsorship of Read the Docs. - Thanks for helping make Open Source more sustainable! + We think that our Ethical Advertising campaign is a wonderful step forward for running ads on open source projects. + You can pay for these ads below.