Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a way for sponsors to pay without asking for logos etc. #2503

Merged
merged 16 commits into from Mar 3, 2017
Merged
5 changes: 0 additions & 5 deletions readthedocs/donate/admin.py
Expand Up @@ -63,11 +63,6 @@ def view_ratio(self, instance):
def click_ratio(self, instance):
return instance.click_ratio() * 100

def total_views(self, instance):
return sum(imp.views for imp in instance.impressions.all())

def total_clicks(self, instance):
return sum(imp.clicks for imp in instance.impressions.all())

admin.site.register(Supporter, SupporterAdmin)
admin.site.register(SupporterPromo, SupporterPromoAdmin)
Expand Down
3 changes: 1 addition & 2 deletions readthedocs/donate/forms.py
Expand Up @@ -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']
)
9 changes: 9 additions & 0 deletions readthedocs/donate/models.py
Expand Up @@ -157,6 +157,15 @@ def views_needed_today(self):
return 0
return ret

def total_views(self):
return sum(imp.views for imp in self.impressions.all())

def total_clicks(self):
return sum(imp.clicks for imp in self.impressions.all())

def total_click_ratio(self):
return '%.4f' % (float(self.total_clicks()) / float(self.total_views()))


class BaseImpression(models.Model):
date = models.DateField(_('Date'))
Expand Down
6 changes: 3 additions & 3 deletions readthedocs/donate/templates/donate/ethicalads-success.html
Expand Up @@ -3,13 +3,13 @@
{% load i18n %}
{% load static %}

{% block title %}{% trans "Sustainability" %}{% endblock %}
{% block title %}{% trans "Sponsorship" %}{% endblock %}

{% block content %}
<h2>Thanks for your support</h2>

<p>
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 <a href="http://docs.readthedocs.io/en/latest/ethical-advertising.html">Ethical Advertising</a> campaign is a wonderful step forward for running ads on open source projects.
Thanks for your support.
</p>
{% endblock %}
3 changes: 2 additions & 1 deletion readthedocs/donate/templates/donate/ethicalads.html
Expand Up @@ -35,7 +35,8 @@ <h2>Pay for your Sponsorship</h2>

<p>
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 <a href="http://docs.readthedocs.io/en/latest/ethical-advertising.html">Ethical Advertising</a> campaign is a wonderful step forward for running ads on open source projects.
You can pay for these ads below.
</p>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same with the title and this paragraph block. Framing this as sponsorship is misleading.


<form action="" method="post" id="donate-payment" class="payment">
Expand Down
52 changes: 52 additions & 0 deletions readthedocs/donate/templates/donate/promo_detail.html
@@ -0,0 +1,52 @@
{% extends "base.html" %}

{% load i18n %}
{% load static %}

{% block title %}{% trans "Promo Detail" %}{% endblock %}

{% block content %}

<h1> Promo Results </h1>

{% for promo in promos %}

<h3>
Results for {{ promo.name }} ({{ promo.analytics_id }}) over last {{ days }} days.
</h3>

<div class="example" style="width: 30%;">
<a href="{{ promo.link }}"><img width=120 height=90 src="{{ promo.image }}"></a>
<br>
{{ promo.text }}

</div>

<br>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whitespace shouldn't be added with html elements, this should be a css change.


<table>
<tr>
<th><strong>Day (UTC)</strong></th>
<th><strong>Views</strong></th>
<th><strong>Clicks</strong></th>
<th><strong>CTR</strong></th>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The <strong> here should also be replace be css rules. We shouldn't dictate styling in the HTML

</tr>
{% for day in promo.impressions.all|slice:days_slice %}
<tr>
<td>{{ day.date }}</td>
<td><code>{{ day.views }}</code></td>
<td><code>{{ day.clicks }}</code></td>
<td><code>{{ day.click_ratio }}%</code></td>
</tr>
{% endfor %}
<tr>
<td><strong>Total (over all time)</strong> </td>
<td><strong>{{ promo.total_views }}</strong></td>
<td><strong>{{ promo.total_clicks }}</strong></td>
<td><strong>{{ promo.total_click_ratio }}%</strong></td>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for styling here. This should perhaps be a rule for table > tr.table-totals or somesuch.

</tr>
</table>

{% endfor %}

{% endblock %}
3 changes: 2 additions & 1 deletion readthedocs/donate/urls.py
@@ -1,14 +1,15 @@
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


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_success'),
url(r'^report/(?P<promo_slug>.+)/$', 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<promo_id>\d+)/(?P<hash>.+)/$', view_proxy, name='donate_view_proxy'),
Expand Down
22 changes: 21 additions & 1 deletion readthedocs/donate/views.py
Expand Up @@ -23,7 +23,7 @@

class PayAdsView(StripeMixin, CreateView):

"""Create a donation locally and in Stripe"""
"""Create a payment locally and in Stripe"""

form_class = EthicalAdForm
success_message = _('Your payment has been received')
Expand Down Expand Up @@ -77,6 +77,26 @@ def get_template_names(self):
return [self.template_name]


class PromoDetailView(TemplateView):
template_name = 'donate/promo_detail.html'

def get_context_data(self, **kwargs):
promo_slug = kwargs['promo_slug']
slugs = promo_slug.split(',')
days = int(self.request.GET.get('days', 90))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Input isn't sanitized here, this should be wrapped for exception handling on TypeError


if promo_slug == 'live' and self.request.user.is_staff:
promos = SupporterPromo.objects.filter(live=True)
else:
promos = SupporterPromo.objects.filter(analytics_id__in=slugs)

return {
'promos': promos,
'days': days,
'days_slice': ':%s' % days,
}


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)
Expand Down