From cf5bd77c5694e54e7f8579e110a9a4b83526b6ee Mon Sep 17 00:00:00 2001 From: "Bradley M. Kuhn" Date: Wed, 14 Jan 2026 14:16:44 -0800 Subject: [PATCH] Support two fundraising bars for a stretch match MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Long ago, when the bar was all Javascript, we had the ability to have sub-targets in a single bar. I was not able to invest the time necessary to figure out how to do that again using the newer setup for the fundraising bar, so instead I've added the ability to have a stretch match bar that appears above the other one once the first match period ends. While it handles most of the weird cases with some grace, it will probably look weird unless you set up a `SITE_FUNDGOAL_0` as a match that finishes at least a week or two before `SITE_FUNDGOAL_1`. The two aren't really aware of each other, either, so you have to make sure the objects are updated properly (i.e., it *will* display the stretch when `SITE_FUNDGOAL_0` ends even if there are match funds remaining in `SITE_FUNDGOAL_0`). A better solution should be found and implemented before 2026-11-22. If you're actually reading this commit message for a reason other than historical interest and that date has past, you're probably in big trouble right now. 😬 --- conservancy/context_processors.py | 10 +- .../fundraiser_goal_banner_partial.html | 141 ++++++++++++------ conservancy/settings/base.py | 4 +- conservancy/static/css/conservancy.css | 3 + 4 files changed, 111 insertions(+), 47 deletions(-) diff --git a/conservancy/context_processors.py b/conservancy/context_processors.py index 9cfd1644..24cb2afc 100644 --- a/conservancy/context_processors.py +++ b/conservancy/context_processors.py @@ -4,10 +4,14 @@ from .fundgoal.models import FundraisingGoal def sitefundraiser(request): try: - fundgoal = FundraisingGoal.objects.get(fundraiser_code_name=settings.SITE_FUNDGOAL) + fundgoal0 = FundraisingGoal.objects.get(fundraiser_code_name=settings.SITE_FUNDGOAL_0) except FundraisingGoal.DoesNotExist: - fundgoal = None - return {'sitefundgoal': fundgoal} + fundgoal0 = None + try: + fundgoal1 = FundraisingGoal.objects.get(fundraiser_code_name=settings.SITE_FUNDGOAL_1) + except FundraisingGoal.DoesNotExist: + fundgoal1 = None + return {'sitefundgoal0': fundgoal0, 'sitefundgoal1': fundgoal1 } def host_url(request): diff --git a/conservancy/fundgoal/templates/fundgoal/fundraiser_goal_banner_partial.html b/conservancy/fundgoal/templates/fundgoal/fundraiser_goal_banner_partial.html index d99a76bc..6086ecce 100644 --- a/conservancy/fundgoal/templates/fundgoal/fundraiser_goal_banner_partial.html +++ b/conservancy/fundgoal/templates/fundgoal/fundraiser_goal_banner_partial.html @@ -1,51 +1,106 @@ {% load humanize %} -{% if sitefundgoal.days_remaining >= -22 %}{# i.e. 7 days over completion #} -
-
-
- {% if sitefundgoal.days_remaining >= 0 %} - {% if sitefundgoal.match_remaining <= 0 %} - Thanks to so many donors, we earned our full match! - Help us go further to stand up for software freedom — sign up now! - {% else %} - {% if sitefundgoal.days_remaining == 0 %} - For the next {{ sitefundgoal.hours_remaining }} hour{{ sitefundgoal.hours_remaining|pluralize }} only, the - {% elif sitefundgoal.days_remaining == 1 %} - Help us reach our goal of $503,878 this season to keep SFC going. Through tomorrow only, the - {% elif sitefundgoal.days_remaining < 14 %} - Help us reach our goal of $503,878 this season to keep SFC going. For only {{ sitefundgoal.days_remaining }} more days, the - {% else %} - Help us reach our goal of $503,878 this season to keep SFC going. Until January 15, the - {% endif %} - next ${{ sitefundgoal.match_remaining|floatformat:0|intcomma }} of support we receive will be matched! - {% endif %} - {% else %} - Thanks to all our donors who participated in our - historic donation match challenge! Thanks to you, we - raised more than $480k to support software freedom: - {% endif %} -
- +{% if sitefundgoal1.days_remaining >= -22 or sitefundgoal0.days_remaining >= -22 %} {# IF LEVEL 0 (only show this at all for 7 days after fundraiser and stretch are over) #} +
+
+
+ {% if sitefundgoal0.match_remaining <= 0 %} {# IF LEVEL 0.1 #} + {% if sitefundgoal1.days_remaining >= 0 %} {# IF LEVEL 0.1.0 #} + {% if sitefundgoal1.match_remaining <= 0 %} {# IF LEVEL 0.1.0.0 #} + Thanks to all our donors who participated in our historic donation match challenge! + Thanks to all of you, we raised our goal of $503,878 to support software freedom: + {% else %} {# ELSE LEVEL 0.1.0.0 when sitefundgoal1.match_remaining > 0 #} + Thanks to so many donors, we met our largest match donation ever of $211,939. + Two generous anonymous donors have provided another ${{ sitefundgoal1.fundraiser_goal_amount|floatformat:0|intcomma }} of additional matching funds. + Give now to help us reach this stretch goal!
+ {% if sitefundgoal1.days_remaining == 0 %} {# IF LEVEL 0.1.0.0.0 sitefundgoal1.days_remaining alternatives #} + For only the next {{ sitefundgoal1.hours_remaining }} hour{{ sitefundgoal1.hours_remaining|pluralize }}, the + {% elif sitefundgoal1.days_remaining == 1 %} {# ELIF LEVEL 0.1.0.0.0 sitefundgoal1.days_remaining alternatives #} + Through tomorrow only, the + {% elif sitefundgoal1.days_remaining < 14 %} {# ELIF LEVEL 0.1.0.0.0 sitefundgoal1.days_remaining alternatives #} + For only {{ sitefundgoal1.days_remaining }} more days, the + {% else %} {# ELIF LEVEL 0.1.0.0.0 sitefundgoal1.days_remaining alternatives #} + Until February 5, the + {% endif %} {# ELSE LEVEL 0.1.0.0.0 sitefundgoal1.days_remaining alternatives #} + next ${{ sitefundgoal1.match_remaining|floatformat:0|intcomma }} of financial support we receive will be matched! + {% endif %} {# ENDIF LEVEL 0.1.0.0 (testing whether or not sitefundgoal1.match_remaining has anything left in it) #} + {% else %} {# ELSE LEVEL 0.1.0 when (sitefundgoal1.days_remaining < 0) #} + {# The problem with automating this is that it does not actually test here if we made the match or not; we are usually watching it so carefully that it should not matter? We also have made ever match we did since 2015, so no one has probably thought hard about this problem. -- bkuhn #} + Thanks to all our donors who participated in our historic donation match challenge! + Thanks to all of you, we raised our goal of $503,878. + Help us go further to stand up for software freedom — sign up now! + {% endif %} {# ENDIF LEVEL 0.1.0 (whether or not there are any sitefundgoal1.days_remaining) #}
- {% if sitefundgoal.match_remaining <= 0 %} -
- ${{ sitefundgoal.fundraiser_goal_amount|floatformat:0|intcomma }} fully matched! -
-
- ${{sitefundgoal.match_exceeded_by|floatformat:0|intcomma }} additional
raised!
-
- {% else %} -
- ${{ sitefundgoal.fundraiser_so_far_amount|floatformat:0|intcomma }} matched! -
-
- ${{ sitefundgoal.match_remaining|floatformat:0|intcomma }} to go! -
- {% endif %} + {% if sitefundgoal1.match_remaining <= 0 %} {# IF LEVEL 0.1.1 #} +
+ ${{ sitefundgoal1.fundraiser_goal_amount|floatformat:0|intcomma }} fully matched! +
+ {% else %} {# ELSE LEVEL 0.1.1 when sitefundgoal1.match_remaining > 0 #} +
+ ${{ sitefundgoal1.fundraiser_so_far_amount|floatformat:0|intcomma }} matched! +
+
+ ${{ sitefundgoal1.match_remaining|floatformat:0|intcomma }} to go! +
+ {% endif %} {# ENDIF LEVEL 0.1.1 testing whether or not sitefundgoal1.match_remaining has anything in it #}
+ +
+ {% if sitefundgoal0.match_remaining <= 0 %} {# IF LEVEL 0.1.2, pointless test of sitefundgoal0.match_remaining (if we get here, else block should never be used!) #} +
+ ${{ sitefundgoal0.fundraiser_goal_amount|floatformat:0|intcomma }} fully matched! +
+ {% else %} {# ELSE LEVEL 0.1.2, sitefundgoal0.match_remaining > 0 , but NOTE! We are here inside IF LEVEL 0.1, so this *should* never appear, included just for consistency #} +
+ ${{ sitefundgoal0.fundraiser_so_far_amount|floatformat:0|intcomma }} matched! +
+
+ ${{ sitefundgoal0.match_remaining|floatformat:0|intcomma }} to go! +
+ {% endif %} {# ENDIF LEVEL 0.1.2, this ends the pointless block here for consistency, see comment above. #} +
+
+ {% else %} {# ELSE LEVEL 0.1 when (sitefundgoal0.match_remaining > 0) #} + {% if sitefundgoal0.days_remaining >= 0 %} {# IF LEVEL 0.1.3 #} + {% if sitefundgoal0.match_remaining <= 0 %} {# IF LEVEL 0.1.3.0 #} + Thanks to so many donors, we earned our full match! + {% else %} {# ELSE LEVEL 0.1.3.0 when sitefundgoal0.match_remaining > 0 #} + {% if sitefundgoal0.days_remaining == 0 %} {# IF LEVEL 0.1.3.0.0 testing options for sitefundgoal0.days_remaining #} + For only the next {{ sitefundgoal0.hours_remaining }} hour{{ sitefundgoal0.hours_remaining|pluralize }}, the + {% elif sitefundgoal0.days_remaining == 1 %} {# ELSIF LEVEL 0.1.3.0.0 testing options for sitefundgoal0.days_remaining #} + Help us reach our goal of $503,878 this season to keep SFC going. Through tomorrow only, the + {% elif sitefundgoal0.days_remaining < 14 %} {# ELSIF LEVEL 0.1.3.0.0 testing options for sitefundgoal0.days_remaining #} + Help us reach our goal of $503,878 this season to keep SFC going. For only {{ sitefundgoal0.days_remaining }} more days, the + {% else %} {# ELSE LEVEL 0.1.3.0.0 testing options for sitefundgoal0.days_remaining #} + Help us reach our goal of $503,878 this season to keep SFC going. Until January 15, the + {% endif %} {# ENDIF LEVEL 0.1.3.0.0 testing options for sitefundgoal0.days_remaining #} + next ${{ sitefundgoal0.match_remaining|floatformat:0|intcomma }} of support we receive will be matched! + {% endif %} {# ENDIF LEVEL 0.1.3.0 testing if sitefundgoal0.match_remaining has anything left #} + {% else %} {# ENDIF LEVEL 0.1.3, when sitefundgoal0.days_remaining < 0 #} + {# The problem with automating this is that it does not actually test here if we made the match or not; we are usually watching it so carefully that it should not matter? We also have made ever match we did since 2015, so no one has probably thought hard about this problem. -- bkuhn #} + Thanks to all our donors who participated in our historic donation match challenge! + Help us go further to stand up for software freedom — sign up now! + {% endif %} {# ENDIF LEVEL 0.1.3, testing if there are any sitefundgoal0.days_remaining left #} + +
+ {% if sitefundgoal0.match_remaining <= 0 %} {# IF LEVEL 0.1.3.1 #} +
+ ${{ sitefundgoal0.fundraiser_goal_amount|floatformat:0|intcomma }} fully matched! +
+ {% else %} {# ELSE LEVEL 0.1.3.1 sitefundgoal0.match_remaining > 0 #} +
+ ${{ sitefundgoal0.fundraiser_so_far_amount|floatformat:0|intcomma }} matched! +
+
+ ${{ sitefundgoal0.match_remaining|floatformat:0|intcomma }} to go! +
+ {% endif %} {# ENDIF LEVEL 0.1.3.1 sitefundgoal0.match_remaining #} +
+
+ {% endif %} {# ENDIF LEVEL 0.1, two choices for based on sitefundgoal0.match_remaining #}
-{% endif %} +
+{% endif %} {# ENDIF LEVEL 0 (the fundraiser has been over for > 7 days) #} diff --git a/conservancy/settings/base.py b/conservancy/settings/base.py index 044ce738..70af53ff 100644 --- a/conservancy/settings/base.py +++ b/conservancy/settings/base.py @@ -162,4 +162,6 @@ USETHESOURCE = { 'LIST_RECIPIENT': 'ccs-review@lists.sfconservancy.org', } -SITE_FUNDGOAL = 'cy2025-end-year-match' +SITE_FUNDGOAL_0 = 'cy2025-end-year-match' +SITE_FUNDGOAL_1 = 'fy2025-26-extend-match' + diff --git a/conservancy/static/css/conservancy.css b/conservancy/static/css/conservancy.css index 408c5d9b..2edfafc9 100644 --- a/conservancy/static/css/conservancy.css +++ b/conservancy/static/css/conservancy.css @@ -1168,6 +1168,9 @@ body > header { #siteprogressbar .soFarText { color: white; } +#siteprogressbar .done { + font-size: 130%; +} #siteprogressbar .exceeded { color: var(--khaki-green); }