Flesh out admin, support multiple donations

master
Drew DeVault 9 years ago
parent 76aae6d57e
commit 6a6cddc5b4
  1. 3
      fosspay/app.py
  2. 11
      fosspay/blueprints/html.py
  3. 4
      fosspay/objects.py
  4. 2
      scripts/index.js
  5. 58
      templates/admin.html
  6. 2
      templates/index.html
  7. 1
      templates/layout.html
  8. 4
      templates/panel.html

@ -74,5 +74,6 @@ def inject():
'user': current_user, 'user': current_user,
'_cfg': _cfg, '_cfg': _cfg,
'_cfgi': _cfgi, '_cfgi': _cfgi,
'debug': app.debug 'debug': app.debug,
'str': str
} }

@ -53,9 +53,11 @@ def admin():
first = request.args.get("first-run") is not None first = request.args.get("first-run") is not None
projects = Project.query.all() projects = Project.query.all()
unspecified = Donation.query.filter(Donation.project == None).all() unspecified = Donation.query.filter(Donation.project == None).all()
donations = Donation.query.order_by(Donation.created.desc()).limit(50).all()
return render_template("admin.html", return render_template("admin.html",
first=first, first=first,
projects=projects, projects=projects,
donations=donations,
one_times=lambda p: sum([d.amount for d in p.donations if d.type == DonationType.one_time]), one_times=lambda p: sum([d.amount for d in p.donations if d.type == DonationType.one_time]),
recurring=lambda p: sum([d.amount for d in p.donations if d.type == DonationType.monthly]), recurring=lambda p: sum([d.amount for d in p.donations if d.type == DonationType.monthly]),
unspecified_one_times=sum([d.amount for d in unspecified if d.type == DonationType.one_time]), unspecified_one_times=sum([d.amount for d in unspecified if d.type == DonationType.one_time]),
@ -108,6 +110,8 @@ def donate():
type = request.form.get("type") type = request.form.get("type")
comment = request.form.get("comment") comment = request.form.get("comment")
project_id = request.form.get("project") project_id = request.form.get("project")
# validate and rejigger the form inputs
if not email or not stripe_token or not amount or not type: if not email or not stripe_token or not amount or not type:
return { "success": False, "reason": "Invalid request" }, 400 return { "success": False, "reason": "Invalid request" }, 400
try: try:
@ -134,8 +138,13 @@ def donate():
customer = stripe.Customer.create(email=user.email, card=stripe_token) customer = stripe.Customer.create(email=user.email, card=stripe_token)
user.stripe_customer = customer.id user.stripe_customer = customer.id
db.add(user) db.add(user)
else:
customer = stripe.Customer.retrieve(user.stripe_customer)
new_source = customer.sources.create(source=stripe_token)
customer.default_source = new_source.id
customer.save()
donation = Donation(user, type, amount, project) donation = Donation(user, type, amount, project, comment)
db.add(donation) db.add(donation)
try: try:

@ -60,14 +60,16 @@ class Donation(Base):
amount = Column(Integer, nullable=False) amount = Column(Integer, nullable=False)
created = Column(DateTime, nullable=False) created = Column(DateTime, nullable=False)
emailed_about = Column(Boolean, nullable=False) emailed_about = Column(Boolean, nullable=False)
comment = Column(String(512))
def __init__(self, user, type, amount, project=None): def __init__(self, user, type, amount, project=None, comment=None):
self.user = user self.user = user
self.type = type self.type = type
self.amount = amount self.amount = amount
self.created = datetime.now() self.created = datetime.now()
self.emailed_about = False self.emailed_about = False
self.project = project self.project = project
self.comment = comment
def __repr__(self): def __repr__(self):
return "<Donation {} from {}: ${} ({})>".format( return "<Donation {} from {}: ${} ({})>".format(

@ -64,6 +64,8 @@
return; return;
} }
donation.comment = document.getElementById("comments").value;
var handler = StripeCheckout.configure({ var handler = StripeCheckout.configure({
name: your_name, name: your_name,
key: window.stripe_key, key: window.stripe_key,

@ -6,9 +6,14 @@
<div class="well"> <div class="well">
<div class="container"> <div class="container">
<p class="pull-right"> <p class="pull-right">
<a class="btn btn-default" href="logout">Log Out</a> <a class="btn btn-primary" href="#" data-toggle="modal" data-target="#donation-button-modal">
Get donation button
</a>
<a class="btn btn-default" href="logout">Log out</a>
</p> </p>
<h1>Donation Admin</h1> <h1>Donation Admin</h1>
<p>Combine this with your <a href="https://dashboard.stripe.com">Stripe
dashboard</a> for the full effect.</p>
</div> </div>
</div> </div>
<div class="container"> <div class="container">
@ -52,7 +57,6 @@
<th>Project Name</th> <th>Project Name</th>
<th>One-time</th> <th>One-time</th>
<th>Recurring</th> <th>Recurring</th>
<th>README Button</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -62,7 +66,6 @@
<td>{{ project.name }}</td> <td>{{ project.name }}</td>
<td>${{ "{:.2f}".format(one_times(project) / 100) }}</td> <td>${{ "{:.2f}".format(one_times(project) / 100) }}</td>
<td>${{ "{:.2f}".format(recurring(project) / 100) }}</td> <td>${{ "{:.2f}".format(recurring(project) / 100) }}</td>
<td><a href="#" class="btn btn-primary btn-sm">Get Markdown</a></td>
</tr> </tr>
{% endfor %} {% endfor %}
<tr> <tr>
@ -70,7 +73,6 @@
<td>(not specified)</td> <td>(not specified)</td>
<td>${{ "{:.2f}".format(unspecified_one_times / 100) }}</td> <td>${{ "{:.2f}".format(unspecified_one_times / 100) }}</td>
<td>${{ "{:.2f}".format(unspecified_recurring / 100) }}</td> <td>${{ "{:.2f}".format(unspecified_recurring / 100) }}</td>
<td></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -86,7 +88,7 @@
</form> </form>
</div> </div>
</div> </div>
<h2>Donation History</h2> <h2>Recent Donations <small>50 most recent</small></h2>
<table class="table"> <table class="table">
<thead> <thead>
<tr> <tr>
@ -94,9 +96,53 @@
<th>Project</th> <th>Project</th>
<th>Comment</th> <th>Comment</th>
<th>Amount</th> <th>Amount</th>
<th style="width: 10%">Recurring</th> <th>Type</th>
</tr> </tr>
</thead> </thead>
<tbody>
{% for donation in donations %}
<tr>
<td><a href="mailto:{{ donation.user.email }}">{{ donation.user.email }}</a></td>
<td>{{ donation.project.name if donation.project else "" }}</td>
<td title="{{ donation.comment }}">{{ donation.comment if donation.comment else "" }}</td>
<td>${{ "{:.2f}".format(donation.amount / 100) }}</td>
<td>{{ "Once" if str(donation.type) == "DonationType.one_time" else "Monthly" }}</td>
</tr>
{% endfor %}
</tbody>
</table> </table>
</div> </div>
<div class="modal fade" id="donation-button-modal" tabindex="-1" role="dialog" aria-labelledby="donation-modal-label">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
<h4 class="modal-title" id="donation-modal-label">Donation buttons</h4>
</div>
<div class="modal-body">
<p>
You can include a donation button in various places to
drive people to your donation page. Here's how it looks:
<a href="..">
<img src="../static/donate-with-fosspay.png" />
</a>
</p>
<p>If you add <code>?project=1</code> to your URL, it will pre-select that project
(where 1 is the 1st project you have listed on this page) when users arrive to donate.</p>
<p><strong>Markdown</strong></p>
<pre>[![Donate with fosspay]({{root}}/static/donate-with-fosspay.png)]({{root}})</pre>
<p><strong>HTML</strong></p>
<pre>&lt;a href="{{root}}"&gt;&lt;img src="{{root}}/static/donate-with-fosspay.png" alt="Donate with fosspay" /&gt;&lt;/a&gt;</pre>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">
Dismiss
</button>
</div>
</div>
</div>
</div>
{% endblock %} {% endblock %}

@ -123,7 +123,7 @@ window.default_type = "{{ _cfg("default-type") }}";
<div class="row"> <div class="row">
<div class="col-md-4 col-md-offset-4"> <div class="col-md-4 col-md-offset-4">
<div class="form-group"> <div class="form-group">
<input type="text" id="comments" class="form-control" placeholder="Any comments?" /> <input type="text" id="comments" class="form-control" placeholder="Any comments?" maxlength="512" />
</div> </div>
</div> </div>
</div> </div>

@ -2,6 +2,7 @@
<html> <html>
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="static/icon.png" type="image/png" /> <link rel="icon" href="static/icon.png" type="image/png" />
{% block title %} {% block title %}
<title>Donate to {{_cfg("your-name")}}</title> <title>Donate to {{_cfg("your-name")}}</title>

@ -3,8 +3,8 @@
<div class="well"> <div class="well">
<div class="container"> <div class="container">
<p class="pull-right"> <p class="pull-right">
<a class="btn btn-primary" href="..">Donate Again</a> <a class="btn btn-primary" href="..">Donate again</a>
<a class="btn btn-default" href="logout">Log Out</a> <a class="btn btn-default" href="logout">Log out</a>
</p> </p>
<h1>Your Donations</h1> <h1>Your Donations</h1>
</div> </div>

Loading…
Cancel
Save