section#news h2 {
color: #263238; }
-section#wishlist {
- background-image: url("../img/wishlist-background.jpg");
- background-size: cover;
- background-position: center center; }
-
.progress {
background-color: rgba(255, 255, 255, 0.2); }
}
}
-section#wishlist {
- background-image: url('../img/wishlist-background.jpg');
- background-size: cover;
- background-position: center center;
-}
-
.progress {
background-color: rgba(255, 255, 255, .2);
}
@keyframes scroll {
0%, 100% { transform: translateY(30%); }
50% { transform: translateY(50%); }
-}
\ No newline at end of file
+}
IP<strong>Fire</strong>
{% elif hostname in ("planet.ipfire.org", "planet.dev.ipfire.org") %}
IP<strong>Fire</strong> Planet
- {% elif hostname in ("wishlist.ipfire.org", "wishlist.dev.ipfire.org") %}
- {{ _("IPFire Wishlist") }}
- <span class="text-muted">{{ _("The IPFire Crowd-Funding Platform") }}</span>
{% else %}
{{ hostname }}
{% end %}
{% if ssl_cipher %}({{ ssl_cipher }}){% end %}
</p>
{% end %}
-
- {% if hostname == "wishlist.ipfire.org" %}
- <p class="pull-right">
- <a href="/terms">{{ _("Terms & Conditions") }}</a>
- </p>
- {% end %}
-
+
<p>© {{ year }} - {{ _("IPFire is free software written by the IPFire Project") }}</p>
</div>
</div>
</div>
</div>
</section>
-
- <section id="wishlist" class="content-section">
- <div class="container">
- <h2 class="display-2 text-center text-white">IP<strong>Fire</strong>’s Wishlist</h2>
-
- {% if hottest_wish %}
- <div class="d-flex flex-row justify-content-between align-items-baseline">
- <h5 class="text-white">{{ hottest_wish.title }}</h5>
-
- {% if hottest_wish.is_new() %}
- <span class="label label-success pull-right">{{ _("NEW") }}</span>
- {% elif hottest_wish.remaining_days and hottest_wish.remaining_days <= 10 %}
- <span>
- {{ _("one day left", "%(num)s days left", hottest_wish.remaining_days) % { "num" : hottest_wish.remaining_days } }}
- </span>
- {% else %}
- <span class="h5 amber-800 hidden-xs-down">
- {{ _("%d%% funded") % hottest_wish.percentage }}
- </span>
- {% end %}
- </div>
-
- <div class="progress progress-small mb-5">
- <div class="progress-bar bg-progress" role="progressbar" aria-valuenow="{{ hottest_wish.percentage_bar }}" aria-valuemin="0" aria-valuemax="100" style="width: {{ hottest_wish.percentage_bar }}%; height: .5rem;">
- <span class="sr-only">{{ _("%.2f%% complete") % hottest_wish.percentage_bar }}</span>
- </div>
- </div>
-
- <p class="text-white small"><a style="color: white; text-decoration: underline;" href="http://wishlist.ipfire.org/wish/{{ hottest_wish.slug }}">Read more</a> about that wish.</p>
- {% end %}
- </div>
- </section>
-
+
<section id="fireinfo" class="content-section">
<div class="container">
<h2 class="display-2 text-center">Fire<strong>Info</strong> Statistics</h2>
+++ /dev/null
-<table class="table-wishlist-widget">
- {% for item in wishlist_items %}
- <tr>
- <td>
- {% if item.is_new() %}
- <span class="label label-success pull-right">{{ _("NEW") }}</span>
- {% elif item.remaining_days and item.remaining_days <= 10 %}
- <span class="pull-right">
- {{ _("one day left", "%(num)s days left", item.remaining_days) % { "num" : item.remaining_days } }}
- </span>
- {% else %}
- <span class="pull-right">
- {{ _("%d%% funded") % item.percentage }}
- </span>
- {% end %}
-
- <a href="http://wishlist.ipfire.org/wish/{{ item.slug }}" target="_blank">{{ item.title }}</a>
-
- <br class="separator-small">
-
- <div class="progress progress-small">
- <div class="progress-bar progress-{{ item.progressbar_colour }}" style="width: {{ "%.2f%%" % item.percentage_bar }};"></div>
- </div>
- </td>
- </tr>
- {% end %}
-</table>
+++ /dev/null
-{% extends "../base-1.html" %}
-
-{% block header %}
- <header class="jumbotron subhead" id="overview">
- <div class="container">
- <h1>{{ _("IPFire Wishlist") }}</h1>
- <p class="lead">
- {{ _("Crowd funding for the IPFire project") }}
- </p>
- </div>
- </header>
-{% end header %}
+++ /dev/null
-{% extends "base.html" %}
-
-{% block title %}{{ _("Closed wishes") }}{% end block %}
-
-{% block body %}
- <div class="page-header">
- <ul class="nav nav-pills pull-right">
- <li>
- <a href="/">{{ _("Wishes open for donation") }}</a>
- </li>
- </ul>
-
- <h1>{{ _("Closed wishes") }}</h1>
- </div>
-
- {% if lang == "de" %}
- <p>
- Auf dieser Seite finden sich bereits ausgelaufene Sammlungen.
- </p>
- {% else %}
- <p>
- On this page, you will find all fundings that have already ended.
- </p>
- {% end %}
-
- <hr>
-
- {% if wishes %}
- {% module Wishlist(wishes) %}
-
- <hr>
-
- <ul class="pager">
- {% if has_next %}
- <li class="previous">
- <a href="/closed?limit={{ limit }}&offset={{ offset + limit }}">← {{ _("Older") }}</a>
- </li>
- {% else %}
- <li class="previous disabled">
- <a href="#">← {{ _("Older") }}</a>
- </li>
- {% end %}
-
- {% if has_previous %}
- <li class="next">
- <a href="/closed?limit={{ limit }}&offset={{ offset - limit }}">{{ _("Newer") }} →</a>
- </li>
- {% else %}
- <li class="next disabled">
- <a href="#">{{ _("Newer") }} →</a>
- </li>
- {% end %}
- </ul>
- {% end %}
-{% end %}
+++ /dev/null
-{% extends "../base.html" %}
-
-{% block title %}{{ wish.title }} - {{ _("Donate") }}{% end block %}
-
-{% block container %}
- <section class="container content-section text-center">
- <div class="page-header">
- <h2>{{ wish.title }}</h2>
- </div>
-
- {% if lang == "de" %}
- <p>
- Bevor du mit deiner Spende fortfährst, lies bitte die
- <a href="/terms">{{ _("Terms & Conditions") }}</a>.
- </p>
- <p>
- Wähle dann deine präferierte Bezahlmethode aus, um deine Spende zu tätigen.
- </p>
- {% else %}
- <p>
- Before you make your donation, make sure that you
- have read the <a href="/terms">{{ _("Terms & Conditions") }}</a>.
- </p>
- <p>
- Then pick one of the methods below to make your donation.
- </p>
- {% end %}
-
- <br class="separator">
-
- <div class="row">
- <div class="col-lg-10 col-md-10 col-lg-offset-1">
- {% module DonationBox(wish.tag) %}
- </div>
- </div>
- </section>
-{% end block %}
+++ /dev/null
-{% extends "base.html" %}
-
-{% block title %}{{ _("Home") }}{% end block %}
-
-{% block body %}
- <section class="content-section text-center">
- <div class="page-header">
- <h1>{{ _("The IPFire Crowd Funding Platform") }}</h1>
- </div>
-
- {% if lang == "de" %}
- <p class="lead">
- Dies ist die IPFire Crowdfunding-Platform, auf welcher du mittels
- Spenden deinem bevorzugten Feature mehr Gewicht verleihen kannst.
- </p>
-
- <p class="lead">
- Es ist ganz einfach. Wähle einen Wunsch, über den du dich freuen
- würdest, wenn er in Zukunft umgesetzt wird.
- Klicke auf den Spenden-Knopf und spende deinen gewünschten Betrag. Teile
- auch deinen Freunden und Kollegen mit, wie sie ihre Wünsche unterstützen
- können.
- </p>
- {% else %}
- <p class="lead">
- The wishlist is the IPFire crowd funding platform where you can
- donate to accelerate the development of your favorite features.
- </p>
-
- <p class="lead">
- It's easy! Just pick the wish you would to see implemented
- in the future. Hit the donate button and donate the amount of
- money this feature is worth for you.
- After that tell your friends and collegues about it and
- encourage them to promote your favourite wish as well.
- </p>
- {% end %}
- </section>
-
- {% if wishes %}
- {% module Wishlist(wishes) %}
- {% else %}
- <div class="alert alert-error ac">
- {% if lang == "de" %}
- <strong>Es tut uns Leid!</strong><br>
- Derzeit finden keine Finanzierungen statt.
- Wenn du das Projekt unterstützen möchtest, so
- tätige eine <a href="http://www.ipfire.org/donation">Spende</a>.
- {% else %}
- <strong>We are sorry!</strong><br>
- There are currently no running fundings.
- If you want to contribute to the project, please
- make a <a href="http://www.ipfire.org/donation">donation</a>.
- {% end %}
- </div>
- {% end %}
-
- <hr>
-
- <div class="row">
- <div class="col-md-6 ac">
- {% if lang == "de" %}
- Du hast eine Idee, oder glaubst ein wichtiges Feature fehlt
- und wäre ideal von der Community finanziert?
- Sende eine E-Mail an:<br>
- <i class="glyphicon glyphicon-envelope"></i> <a href="mailto:wishlist@ipfire.org">wishlist@ipfire.org</a>
- {% else %}
- Do you think we are missing a great feature that could be
- funded by the community? Write us an email about it to:<br>
- <i class="glyphicon glyphicon-envelope"></i> <a href="mailto:wishlist@ipfire.org">wishlist@ipfire.org</a>
- {% end %}
- </div>
-
- <div class="col-md-6 ac">
- {% if lang == "de" %}
- Bereits fertiggestellte Sammlungen finden sich
- <a href="/closed">hier</a>.
- {% else %}
- Already closed fundings are to be found over
- <a href="/closed">here</a>.
- {% end %}
- </div>
- </div>
-{% end block %}
+++ /dev/null
-<div class="panel panel-default">
- <div class="panel-body">
- {% if not short %}
- {% if wish.remaining_days <= 10 and wish.remaining_days >= 0 %}
- <span class="label label-primary pull-right">
- {{ _("Only a few days left!") }}
- </span>
- {% end %}
-
- <h3>
- <a href="/wish/{{ wish.slug }}">{{ wish.title }}</a>
- </h3>
-
- <hr>
-
- {% raw wish.description %}
-
- <hr>
- {% end %}
-
- <div class="progress">
- <div class="progress-bar {{ progress_bar }}" style="width: {{ "%.2f%%" % wish.percentage_bar }};"></div>
- </div>
- </div>
-
- <div class="panel-footer">
- <div class="row">
- <div class="col-lg-3 col-md-3 ac">
- <br><br>
- <a class="btn btn-lg btn-primary" href="/wish/{{ wish.slug }}/donate">
- {{ _("Donate") }}
- </a>
- <br><br>
- </div>
-
- <div class="col-lg-6 col-md-6">
- <div class="well">
- <div class="row">
- <div class="col-lg-4 col-md-4 ac">
- <p class="lead">{{ "%d%%" % wish.percentage }}</p>
- <p>{{ _("funded") }}</p>
- </div>
-
- <div class="col-lg-4 col-md-4 ac">
- <p class="lead">{% raw _("%s €") % wish.donated %}</p>
- <p>{{ _("donated") }}</p>
- </div>
-
- <div class="col-lg-4 col-md-4 ac">
- {% if wish.status == "running" %}
- {% if wish.remaining_days %}
- <p class="lead">{{ wish.remaining_days }}</p>
- <p>{{ _("day to go", "days to go", wish.remaining_days) }}</p>
- {% else %}
- <p class="lead">{% raw _("%s €") % (wish.goal - wish.donated) %}</p>
- <p>{{ _("to go") }}</p>
- {% end %}
- {% elif wish.status == "in_progress" %}
- <p class="lead">{{ _("In progress") }}</p>
- {% elif wish.status == "finished" %}
- <p class="lead">{{ _("Finished") }}</p>
- {% else %}
- <p class="lead">{{ _("Funding ended") }}</p>
- {% end %}
- </div>
- </div>
- </div>
- </div>
-
- <div class="col-lg-3 col-md-3">
- <br>
- <p class="ac">
- {{ _("Share this wish with your friends and help us promote it!") }}
- </p>
- </div>
- </div>
- </div>
-</div>
+++ /dev/null
-{% for wish in wishes %}
- {% module Wish(wish, short=short) %}
-{% end %}
+++ /dev/null
-{% extends "base.html" %}
-
-{% block title %}{{ _("Terms & Conditions") }}{% end block %}
-
-{% block body %}
- <div class="page-header">
- <h1>{{ _("Terms & Conditions") }}</h1>
- </div>
-
- {% if lang == "de" %}
- <p>
- Vielen Dank, dass du zum IPFire-Projekt beitragen möchtest.
- Mit deiner Spende erklärst du dich mit den folgenden Regeln und Bedingungen
- einverstanden.
- </p>
- <p>
- Es wird nicht auf einen präferierten Wunsch gespendet, sondern eine
- Spende an das Projekt entrichtet, die dir die Möglichkeit gibt
- deinen Wunsch nach oben zu befördern.
- </p>
- <p>
- Es kann nicht garantiert werden, dass dein favorisierter Wunsch
- (z.B. aus technischen Gründen) implementiert wird.
- Die gesammelte Spendensumme wird dann für die Finanzierung
- anderer Teile des Projekts verwendet.
- </p>
- <p>
- Mehr Informationen über Spenden finden sich auf unserer
- <a href="http://www.ipfire.org/donation">Spenden</a>-Seite.
- </p>
- {% else %}
- <p>
- Thank you for contributing to the IPFire project.
- By donating, you agree to be bound by the following terms and conditions.
- If you don't agree to be bound or cannot comply with any of the terms
- and conditions, do not continue the donations.
- </p>
- <p>
- You don't donate on a feature, you donate money to the project
- and with that donation comes the option to recommend that a certain
- feature should be implemented.
- </p>
- <p>
- There is no guarantee that your favorite feature will ever be implemented
- - e.g. because of technical reasons.
- If your feature will not be implemented,
- your donations will then be used to fund other parts of the project.
- </p>
- <p>
- More information about donations can be found on our
- <a href="http://www.ipfire.org/donation">donation</a> page.
- </p>
- {% end %}
-{% end block %}
+++ /dev/null
-{% extends "base.html" %}
-
-{% block title %}{{ wish.title }} - {{ _("Wish") }}{% end block %}
-
-{% block body %}
- <div class="page-header">
- <h1>{{ wish.title }}</h1>
- </div>
-
- {% module Wishlist([wish,], short=True) %}
-
- {% raw wish.description %}
-
- <hr>
-
- <p class="ac">
- <i class="glyphicon glyphicon-calendar"></i>
- {{ _("Launched: %s") % locale.format_date(wish.date_start, full_format=True) }}
-
- •
-
- {% if wish.date_end %}
- <i class="glyphicon glyphicon-time"></i>
- {{ _("Funding ends: %s") % locale.format_date(wish.date_end, full_format=True) }}
- {% else %}
- {{ _("This funding runs until the goal is reached.") }}
- {% end %}
- </p>
-{% end block %}
"TalkCallLog" : TalkCallLogModule,
"TalkLines" : TalkLinesModule,
"TalkOngoingCalls" : TalkOngoingCallsModule,
- "Wish" : WishModule,
- "Wishlist" : WishlistModule,
- "WishlistItems" : WishlistItemsModule,
},
xsrf_cookies = True,
)
(r"/view/(.*)", NopasteViewHandler),
] + authentication_handlers + static_handlers)
- # wishlist.ipfire.org
- self.add_handlers(r"wishlist(\.dev)?\.ipfire\.org", [
- (r"/", WishlistIndexHandler),
- (r"/closed", WishlistClosedHandler),
- (r"/wish/(.*)/donate", WishDonateHandler),
- (r"/wish/(.*)", WishHandler),
- (r"/terms", WishlistTermsHandler),
- ] + static_handlers)
-
# geoip.ipfire.org
self.add_handlers(r"geoip(\.dev)?\.ipfire\.org", [
(r"/", GeoIPHandler),
import releases
import settings
import talk
-import wishlist
class Backend(object):
def __init__(self, configfile, debug=False):
self.planet = planet.Planet(self)
self.releases = releases.Releases(self)
self.talk = talk.Talk(self)
- self.wishlist = wishlist.Wishlist(self)
def read_config(self, configfile):
cp = configparser.ConfigParser()
+++ /dev/null
-#!/usr/bin/python
-
-from __future__ import division
-
-import datetime
-import textile
-
-from misc import Object
-
-class Wishlist(Object):
- def get(self, slug):
- wish = self.db.get("SELECT * FROM wishlist WHERE slug = %s", slug)
-
- if wish:
- return Wish(self, wish.id)
-
- def get_all_by_query(self, query, *args):
- wishes = []
-
- for row in self.db.query(query, *args):
- wish = Wish(self, row.id, row)
- wishes.append(wish)
-
- return wishes
-
- def get_all_running(self):
- return self.get_all_by_query("SELECT * FROM wishlist \
- WHERE (CASE \
- WHEN date_end IS NULL THEN \
- NOW() >= date_start AND goal >= donated \
- ELSE \
- NOW() BETWEEN date_start AND date_end \
- END) AND status = 'running' \
- ORDER BY prio ASC, date_end ASC")
-
- def get_all_finished(self, limit=5, offset=None):
- query = "SELECT * FROM wishlist \
- WHERE (CASE \
- WHEN date_end IS NULL THEN \
- donated >= goal \
- ELSE \
- NOW() > date_end \
- END) AND status IS NOT NULL \
- ORDER BY date_end DESC"
- args = []
-
- if limit:
- query += " LIMIT %s"
- args.append(limit)
-
- if offset:
- query += " OFFSET %s"
- args.append(offset)
-
- return self.get_all_by_query(query, *args)
-
- def get_hot_wishes(self, limit=3):
- query = "SELECT * FROM wishlist \
- WHERE \
- status = %s \
- AND \
- date_start <= NOW() \
- AND \
- (CASE WHEN date_end IS NOT NULL THEN \
- NOW() BETWEEN date_start AND date_end \
- ELSE \
- TRUE \
- END) \
- AND \
- (AGE(NOW(), date_start) <= INTERVAL '10 days' \
- OR \
- AGE(date_end, NOW()) <= INTERVAL '14 days' \
- OR \
- (donated / goal) >= 0.85 \
- OR \
- goal >= 3000 \
- OR \
- prio <= 5 \
- ) \
- ORDER BY prio ASC, date_end ASC LIMIT %s"
-
- return self.get_all_by_query(query, "running", limit)
-
- def get_hottest_wish(self):
- wishes = self.get_hot_wishes(limit=1)
-
- if wishes:
- return wishes[0]
-
-
-class Wish(object):
- def __init__(self, wishlist, id, data=None):
- self.wishlist = wishlist
- self.id = id
-
- self.__data = data
-
- def __repr__(self):
- return "<%s %s>" % (self.__class__.__name__, self.title)
-
- def __cmp__(self, other):
- return cmp(self.date_end, other.date_end)
-
- @property
- def db(self):
- return self.wishlist.db
-
- @property
- def data(self):
- if self.__data is None:
- self.__data = self.db.get("SELECT * FROM wishlist WHERE id = %s", self.id)
- assert self.__data
-
- return self.__data
-
- @property
- def title(self):
- return self.data.title
-
- @property
- def title_short(self):
- if len(self.title) > 30:
- return "%s..." % self.title[:30]
-
- return self.title
-
- @property
- def slug(self):
- return self.data.slug
-
- @property
- def tag(self):
- return self.data.tag
-
- @property
- def description(self):
- return textile.textile(self.data.description)
-
- @property
- def goal(self):
- return self.data.goal
-
- @property
- def donated(self):
- return self.data.donated
-
- @property
- def percentage(self):
- return (self.donated / self.goal) * 100
-
- @property
- def percentage_bar(self):
- if self.percentage > 100:
- return 100
-
- return self.percentage
-
- @property
- def progressbar_colour(self):
- if self.is_new():
- return "bar-success"
-
- if self.percentage >= 90:
- return "bar-danger"
-
- return "bar-warning"
-
- @property
- def status(self):
- if self.data.status == "running" and not self.running:
- return "closed"
-
- return self.data.status
-
- @property
- def running(self):
- if self.date_end:
- if self.remaining_days and self.remaining_days < 0:
- return False
-
- else:
- if self.donated >= self.goal:
- return False
-
- return True
-
- @property
- def date_start(self):
- return self.data.date_start
-
- @property
- def date_end(self):
- return self.data.date_end
-
- @property
- def running_days(self):
- running = datetime.datetime.today() - self.date_start
- return running.days
-
- @property
- def remaining_days(self):
- if self.date_end:
- remaining = self.date_end - datetime.datetime.today()
- return remaining.days
-
- def is_new(self):
- return self.running_days < 10
-
- def get_tweet(self, locale):
- _ = locale.translate
-
- t = [
- _("Checkout this crowdfunding wish from #ipfire:"),
- "http://wishlist.ipfire.org/wish/%s" % self.slug,
- ]
-
- return " ".join(t)
from handlers_planet import *
from handlers_rss import *
from handlers_talk import *
-from handlers_wishlist import *
class RootHandler(BaseHandler):
"""
# Get a list of the most recent news items and put them on the page.
latest_news = self.get_latest_news()
- # Interesting items from the wishlist.
- hottest_wish = self.wishlist.get_hottest_wish()
-
return self.render("index.html", latest_news=latest_news,
- latest_release=latest_release, hottest_wish=hottest_wish)
+ latest_release=latest_release)
def get_latest_news(self, count=5):
latest_news = []
class DonateHandler(BaseHandler):
def get(self):
- reason_for_transfer = self.get_argument("reason_for_transfer", None)
-
- # Interesting items from the wishlist.
- wishlist_items = self.wishlist.get_hot_wishes()
-
- self.render("donate.html", wishlist_items=wishlist_items,
- reason_for_transfer=reason_for_transfer)
+ self.render("donate.html")
class DownloadHandler(BaseHandler):
def planet(self):
return self.backend.planet
- @property
- def wishlist(self):
- return self.backend.wishlist
-
class LoginHandler(BaseHandler):
def get(self):
+++ /dev/null
-#!/usr/bin/python
-
-import tornado.web
-
-from handlers_base import *
-
-class WishlistIndexHandler(BaseHandler):
- def get(self):
- wishes = self.wishlist.get_all_running()
-
- self.render("wishlist/index.html", wishes=wishes)
-
-
-class WishlistClosedHandler(BaseHandler):
- def get(self):
- limit = self.get_argument("limit", None)
- offset = self.get_argument("offset", None)
-
- try:
- limit = int(limit)
- except:
- limit = 5
-
- try:
- offset = int(offset)
- except:
- offset = 0
-
- wishes = self.wishlist.get_all_finished(limit=limit + 1, offset=offset)
-
- if len(wishes) > limit:
- wishes = wishes[:limit]
- has_next = True
- else:
- has_next = False
-
- if offset:
- has_previous = True
- else:
- has_previous = False
-
- self.render("wishlist/closed.html", wishes=wishes, limit=limit, offset=offset,
- has_next=has_next, has_previous=has_previous)
-
-
-class WishlistTermsHandler(BaseHandler):
- def get(self):
- return self.render("wishlist/terms.html")
-
-
-class WishHandler(BaseHandler):
- def get(self, slug):
- wish = self.wishlist.get(slug)
- if not wish:
- raise tornado.web.HTTPError(404, "Could not find wish %s" % slug)
-
- self.render("wishlist/wish.html", wish=wish)
-
-
-class WishDonateHandler(BaseHandler):
- def get(self, slug):
- wish = self.wishlist.get(slug)
- if not wish:
- raise tornado.web.HTTPError(404, "Could not find wish %s" % slug)
-
- self.render("wishlist/donate.html", wish=wish)
def talk(self):
return self.handler.talk
- @property
- def wishlist(self):
- return self.handler.wishlist
-
class AdvertisementModule(UIModule):
def render(self, where):
account=account, channels=channels, debug=debug)
-class WishlistModule(UIModule):
- def render(self, wishes, short=False):
- return self.render_string("wishlist/modules/wishlist.html",
- wishes=wishes, short=short)
-
-
-class WishModule(UIModule):
- def render(self, wish, short=False):
- progress_bar = "progress-bar-warning"
-
- if wish.percentage >= 100:
- progress_bar = "progress-bar-success"
-
- return self.render_string("wishlist/modules/wish.html",
- wish=wish, short=short, progress_bar=progress_bar)
-
-
-class WishlistItemsModule(UIModule):
- def render(self, wishlist_items):
- return self.render_string("modules/wishlist-items.html",
- wishlist_items=wishlist_items)
-
-
class DonationBoxModule(UIModule):
def render(self, reason_for_transfer=None):
if reason_for_transfer: