Open jrosindell opened 3 years ago
Page design.
Should be a list of all leaves by the user with that e-mail Should be a tick box for each one that needs renewal Should work like sponsor leaf page with 'accept terms and donate now' button.
James and Yan to draw a mockup with labelled actions on it then hope to outsource if feasible
Notes from meeting:
This is starting to come together, and displaying the various categories of sponsorships. Still a bit too messy to commit, but it's here if you're curious: https://github.com/lentinj/OZtree/tree/wip-363
I've created a test/fixtures/reservations.sql
that will move existing entries aside, and populate with a bunch of made-up sponsorships in different states. As well as being useful for developing / testing, the fixture sponsors will probably be useful for inspecting the end-result in various modes and edge cases.
Great, thanks for setting up the test fixture(s) - should be really useful. Don't hesitate to reorganise anything in the tests/
dir, as I didn't really know what I was doing when setting it up.
I've just thought of an edge case - which is that some leaves will have price = NULL and yet are sponsored e.g. the panda.
Maybe in such cases we should take the price paid before as the renewal.
Alternatively we make a note saying this leaf must be renewed by consultation over e-mail.
I think these are in the "banned" list (a separate table), so we could give those leaves a price (the price paid) and I think they will still be listed as "contact us" in the sponsorship box
Okay, presumably we should also show a hint at the bottom, before the donate button. having 1 "banned" item out of ~50 sponsorships won't be particularly obvious if you're trying to renew the lot.
There's only one (out of ~20) species that are "banned" that have been sponsored so far. So we shouldn't put too much effort into making this aspect look perfect.
This is starting to come together. The fixture SQL generates some standard users for playing, so you don't have to recreate conditions, have a go with:
/sponsor_renew.html/fixture_single@example.com
/sponsor_renew.html/fixture_agemixture@example.com
/sponsor_renew.html/fixture_bannedott@example.com
Some TODOs and questions:
sponsorship.allow_sponsorship
and others, banning the renewal page from places we don't expect it to work.So how does the fixture stuff work, if you have an existing reservations table (as I do on my local version)? If I checkout the 3.5 branch and go to 127.0.0.1:8000/sponsor_renew.html/fixture_single@example.com
I get
<class 'AttributeError'> 'NoneType' object has no attribute 'fetchone'
Version web2py™ Version 2.21.1-stable+timestamp.2020.11.27.18.21.43 Python Python 3.9.4: /Users/yan/opt/miniconda3/bin/python3 (prefix: /Users/yan/opt/miniconda3) Traceback (most recent call last): File "/Users/yan/Documents/Research/OneZoom/web2py/gluon/restricted.py", line 219, in restricted exec(ccode, environment) File "/Users/yan/Documents/Research/OneZoom/web2py/applications/OZtree/controllers/default.py", line 1968, in
File "/Users/yan/Documents/Research/OneZoom/web2py/gluon/globals.py", line 430, in self._caller = lambda f: f() File "/Users/yan/Documents/Research/OneZoom/web2py/applications/OZtree/controllers/default.py", line 837, in sponsor_renew for r in db(db.reservations.e_mail == user_email).iterselect( File "/Users/yan/Documents/Research/OneZoom/web2py/gluon/packages/dal/pydal/objects.py", line 3563, in iter row = next(self) File "/Users/yan/Documents/Research/OneZoom/web2py/gluon/packages/dal/pydal/objects.py", line 3535, in next db_row = self.cursor.fetchone()
But it may be that I have a too-old version of pymysql
or something
So how does the fixture stuff work
It's not fancy, it's just a SQL script to run that moves the table content to one side and populates with known values: https://github.com/OneZoom/OZtree/blob/3.5/tests/fixtures/reservations.sql
Possibly upgrading pymysql
would help, or could try replacing iterselect()
with select()
, looks like the former is exercising codepaths the MySQL driver can't use.
So how does the fixture stuff work
It's not fancy, it's just a SQL script to run that moves the table content to one side and populates with known values: https://github.com/OneZoom/OZtree/blob/3.5/tests/fixtures/reservations.sql
Right, but when does it actually run? Is it triggered by something specific in the test suite? I'm assuming visiting a url outside of the test suite won't work (as the correct info isn't in the DB)
Possibly upgrading
pymysql
would help, or could try replacingiterselect()
withselect()
, looks like the former is exercising codepaths the MySQL driver can't use.
I seem to have v 1.0.2 of pymysql
installed, which is, I think, the latest. So I presume it's not that. And I seem to be running the latest web2py (and mysql 8.0). So I'm not sure what the issue is.
Right, but when does it actually run? Is it triggered by something specific in the test suite? I'm assuming visiting a url outside of the test suite won't work (as the correct info isn't in the DB)
The idea is that you can run it yourself with your preferred mysql client for visual checks outside a test suite, or a test suite would execute it as part of setUpClass()
.
So I'm not sure what the issue is.
Did replacing iterselect()
make the issue go away?
Possibly upgrading
pymysql
would help, or could try replacingiterselect()
withselect()
, looks like the former is exercising codepaths the MySQL driver can't use.
If I use "select" instead, I get:
Traceback (most recent call last): File "/Users/yan/Documents/Research/OneZoom/web2py/gluon/restricted.py", line 219, in restricted exec(ccode, environment) File "/Users/yan/Documents/Research/OneZoom/web2py/applications/OZtree/views/default/sponsor_renew.html", line 209, in
AttributeError: 'NoneType' object has no attribute 'e_mail'
I assume this is an issue with looking for a non-existent email in the DB (since I didn't run the fixture code first).
Yup, non-existent e-mail. The above stops using iterselect and patches things to the point an empty page can render, although presumably we should have a more obvious "You haven't sponsored anything, here's how" message in this case.
I think iterselect()
rather than select()
is fine as long as the edge case of no returned items is covered.
A few comments after reviewing the page as it stands now....
For the message about not gift-aiding. I'd suggest....
We do not have a gift aid declaration from you. If you are a UK tax payer please consider making a Gift Aid declaration which will increase the value of your donation by 25% at no cost to you. If you sponsor any new leaf you will be able to make a gift aid declaration as part of that process and this declaration would also apply to any donation you make here to renew existing leaves. Alternatively, if you want to make a new gift aid declaration without sponsoring any new leaves please write to us.
If people add to their donation amount - how will this be posted.
The other option would be to record the extra donation separately, which could be useful if you then accept donations without sposorship, but probably isn't worth the faff. I was assuming it would be divided amongst the sponsored items arbitrarily, as you say.
I've changed the behavior (or will once it's pushed) of the donation amount box, before it was making sure that the amount was at least the required amount, now if I deselect a renewal, the amount will go down too. I think this is more intuitive, but thoughts welcome.
We could try and work out if there was an extra amount added on deselect and preserve it, but I don't think it's worth it. If we still think this is confusing, I think we separate the price out into (x) for leaves + (y) extra donation.
What about a separate box or radio button to add 5,10,20, some other amount to your sponsorship? To keep things simple I think the extra could be added to whichever is first (according to some ordering) to save the hassle of another table / system to record extra donations.
Okay, lets keep it separate in the UI.
In the DB if it's added to whichever is first that makes it easier to reconstitute the extra donation too.
Yes I think that's best - because which donation the extra is added to doesn't really matter as long as it sums to the correct amount
I think all your comments from before are now sorted.
should we have a link to each leaf on the tree that opens as a new tab? I think yes we should.
We already did (on the image), but I've added "leafout" styling from the homepage, which is what it should have had. Or do you mean the text also?
For the 'donate' button...
I've turned this into a pill for now too, to make it work I've moved the terms/conditions link to a paragraph above. Seem reasonable? I think this looks better than the paypal
I think the pill choice and leaflet styling sound like the ideal solutions here.
Note the above commit restructures how the reservations fixture is formed, they're now agemixture@fixture.example.com
in line with unit tests.
I've just been trying the unit tests in applications/OZtree/tests/unit/test_modules_sponsorship.py
and I forgot that a new installation won't have prices set on any of the leaves, so perhaps it's worth having a test that checks for at least one non-null price in ordered_leaves
and if not, reports an error that says "You need to set prices first by going to http://127.0.0.1:8000/manage/SET_PRICES
" (or whatever the URL is for the local server)
@lentinj - I think it would be helpful to add a README.md file to ./tests/
which gives brief instructions for how to run the tests (and maybe a (very short) explanation for how they work - e.g. "tests in unit/test_modules_sponsorship.py
add a few rows to the existing reservations table, and delete them at the end of the tests". What do you think?
When visiting the sponsor_renew.html
page, and locating an item where user_donor_show = NULL, currently the page treats this as equivalent to 0, and unticks the "show on donor page" checkbox. However we want it to be equivalent to 1 instead. The rationale for this is that 0 means the user has already before been given the option to show and decided not to, whereas NULL means they have never been asked. Yan and I think if they haven't been asked, it's OK to tick the checkbox by default, because basically the whole thing is about sponsorship, which means making public your donation.
If I try to look at a renewals page with
[sponsorship]
allow_sponsorship = manager
in my appconfig.ini file, I get the following error message:
What should happen is that allow_sponsorship
should be able to be set to 0, 1, or a group name. If a group name, then if the user is logged in and the user belongs to the group specified, then it acts as a 0, otherwise it acts as a 0. This allows us to test on beta.onezoom.org, where we set allow_sponsorship = manager
so that we can test all the sponsoring framework, but a causal visitor who accidentally ends up on the beta site cannot see anything to do with sponsorship.
Another (very minor) issue is that I think the text that currently says "Now sponsored by Fixture Single", but I think it should say "Sorry, this leaf has now been sponsored by someone else".
I think it would be helpful to add a README.md
Yes, I was going to bring up this as part of the testing ticket, and explain the fixtures as well. We could also do with a test runner wrapping this and any others in future, probably an extra task in the Gruntfile since that's what's already there.
Another (very minor) issue is that I think the text that currently says "Now sponsored by Fixture Single", but I think it should say "Sorry, this leaf has now been sponsored by someone else".
@jrosindell I think the wording came from your mockups, any comments? Changing it simplifies the code, since it doesn't need to dig out the current sponsor any more.
When visiting the sponsor_renew.html page, and locating an item where user_donor_show = NULL, currently the page treats this as equivalent to 0, and unticks the "show on donor page" checkbox. However we want it to be equivalent to 1 instead.
The web2py DAL seems to be doing this for us, boolean fields seem to assume NULL == False, so it's not as simple as adding another check in the view. Worth digging deeper to sort out?
We could shift the field name to user_donor_hide
, and negate all the existing 0/1 values?
I'm assuming there's a "don't do that" option in the DAL that's going to be quicker to find than recreating the field. But yes, user_donor_hide
is probably the more natural way around.
We're going to be fiddling with (a copy of) the main reservations table to get it into the correct format anyway, so I think a small change from 0<->1 plus a rename would be OK, if it makes the whole thing more sane.
Amassing remaining TODOs:
user_donor_hide
(added by Yan)
sponsor_renew
page without any private info, without the "expired reservations" list, and not broken down into existing + coming up for renewal). Currently listed as "There is also a public page available at TODO: that you can share if you wish." at the top of the sponsor_renew
page.For the token-renewal, web2py has signed URLs, which is pretty much what we're after. There's no built-in concept of link expiry though, should we add one and if so how long should they last?
Why would we want the link to expire? I think the donor would expect this to be a permanent link, wouldn't they?
Why would we want the link to expire? I think the donor would expect this to be a permanent link, wouldn't they?
but this wouldn't apply to the "public" donor page (#364), would it? I think we decided that for that, we would create a permanent link out of the reservations.username
field. I can't recall how we get people to populate that field, though (or if we do so automatically from the verified_donor_name
somehow. Do you remember @jrosindell ?
For the token-renewal, web2py has signed URLs, which is pretty much what we're after. There's no built-in concept of link expiry though, should we add one and if so how long should they last?
I think that @jrosindell opened a specific issue about tokens at https://github.com/OneZoom/OZtree/issues/393, so maybe this is a good discussion to move there?
Re the public page, I've just opened a discussion of usernames at #394
For user_donor_hide
, what would the sponsor form text get replaced with?
Do you mean what should we change it to in sponsor_leaf
now that they will also get a "donor" page, or what should the (mouseover?) text be in the sponsor_renew page?
If the former, perhaps something like this:
{{=XML(T('We would love to be able to thank you by name: if this box is ticked we’ll add your name to our public %s and create a page for your sponsorships that you can show to others, if you wish.') % (A(T('list of donors'), _href='/donor_list', _target="blank"),))}}
I mean if user_donor_show
becomes user_donor_hide
, and the linked checkbox's action inverts, what would the label become?
I'd suggest this....
Your sponsorship includes a public acknowledgement of your donation. We now acknowledge donors on our tree of life explorer, on our public list of donors, and if you wish you can create a personal page of your sponsorships that you can show to others. Tick this box if you would prefer this sponsorship to be acknowledged on the tree only.
@hyanwong https://github.com/OneZoom/OZtree/commit/5d158910e6755e8dd12430c18b8a70b833c78870 switches to user_donor_hide
, but there's nothing to do the migration itself, presumably you'll add it to your list somewhere?
Yep, we'll need to make a list of everything that needs to be done for the one-off migration
As discussed in #304 I've so far had problems accessing this page in the deployment.