Community app for Corona Virus 'Lock-down'

Edit:

If you’d like to find out more about WGACA or get involved, please get in contact with @WGACA directly or check out their Github page:


Original Post:

Hi all, I’m still recovering from 8 days of fever and Corona Virus and using the time to make a simple but hopefully helpful app to share ASAP with my local community and (if it’s any good) further afield too.

In essence the app allows people to post urgent requests for food, drink, household goods, and over-the-counter medicine and tries to match it with other people posting items they have to spare. It connects the dots and allows people to volunteer to make deliveries, and builds up a kind of reputation score for registered users over time to discourage selfishness, greed, and scamming. If it grows, my intention is to make the app and the data available to other charities (e.g. food banks), community groups, emergency services and other agencies who are better placed to manage logistics/distribution using the tool.

It’s called WHAT GOES AROUND COMES AROUND (WGACA) which I hope captures the philosophy of helping each other out during a crisis and also the goal of physically moving items around the neighbourhood to where they’re most needed.

I’m posting some screenshots to give you a better idea… If they inspire anyone to offer their time to collaborate with me on this project I’d love to hear from you. And finally a BIG thank you to Meredydd Luff and team for their huge generosity donating a business account so we could get this off the ground - the back end Python was never the problem, but Anvil has offered a way of sharing this with non-technical neighbours quickly and with minimal effort/learning.

I’ll post more details about the sort of help I’m looking for depending on the response…

All the best, and stay safe.
peter@southwestlondon.tv

OFFERS - People post what they can spare...

REQUESTS - People ask for things they urgently need:

MATCHES - Backend Python tries to connect Offers and Requests, and allows people to volunteer as 'Runners' to deliver:

DELIVERIES - Volunteer 'Runners' are presented with an itinerary for pick-ups & drop-offs:

DATA - Rudimentary account admin:

10 Likes

Great project great idea!
As I wrote on another post, I was thinking at something similar but then stopped.

I’m definitely in with this! Let me know what kind of help I might offer.
I can code python and know Anvil at (at least I think) some acceptable level.

And if you allow me, I could translate the app in italian and use it here too.

1 Like

Great to hear from you Aldo and thanks for the offer of help! I’m self-taught in Python (2 years) and have just 4 days experience with Anvil… just so you know you’re dealing with a relative newbie… and the app is still only a part-working prototype but I hope to have the Minimum Working Product (0.1) by the end of this weekend, particularly if you can help or others can help…

No objection at all to you translating it into Italian but suggest we get the app to Version 0.1 as a stable baseline first (that way we won’t have to change layout or text, or re-translate).

Here’s a list of my most urgent priorities and some bigger challenges for future versions:

  1. PETER. I’m not sure the best way to collaborate with Anvil apps - I got stuck creating a Git repository which could be shared and version controlled in the normal way with Issues, Pull Requests etc. so if you know how we should manage things please feel free to take the lead, otherwise I think I can just copy the app and send the link to you privately so you set up your own version on Anvil, but then how do we merge your changes into mine? And what if other people get involved?

  2. PETER. I need to customise the Login/Registration process to force users to enter an Address (House Number, Street, Town/City, County/Borough, and Post Code). There can only be one registered User per Address (in order to prevent scammers). They also need to select a Display Name that hasn’t been chosen yet and (ideally) isn’t something rude or offensive! I’ve read the tutorial on customising the Login/Registration process but not got my head around what I need to do yet. Ideally one unified form for Login/Registration but with validation logic to check the above.

  3. COMPLETE. I need a simple function to initiate a Password reset.

  4. ALDO. I need to make the Telephone field editable from the Data view. Again I’ve read the Anvil tutorial on this, but haven’t got my head around it yet.

  5. PETER. I need a function to completely delete the account and all* data, after giving a warning. To prevent scamming, that Address must be prevented from automatically re-registering without some kind of check. (*) I’m no expert at IT security, but it might be helpful to retain some sort of log of “bad” accounts e.g. email addresses used, IP addresses, Display Names, and actual Addresses?

  6. I need a function to estimate the distance between the Offer address and the Request address of a match - perhaps a call to Google Maps or other mapping service? I notice the REST API of Google Maps is pretty trivial - if we can generate this type of URL and open a new tab in the webbrowser (or create an iframe) then this will be a great start:
    https://www.google.co.uk/maps/dir/30+Chartfield+Ave,+London+SW15+6HG/35+Putney+Hill,+Putney,+London+SW15+6BH/

The User table in the app already records House Number, Street, Town/City (e.g. Putney - optional for Google Maps), County/Borough (e.g. London), and Postcode (e.g. SW15 6BH).

There’s probably a more elegant API for getting the distance back from Google Maps but it should also be possible to simply scrape the results by looking for the following with BeautifulSoup/Selenium etc.:

<div jstcache="451" class="section-directions-trip-distance section-directions-trip-secondary-text" jsan="7.section-directions-trip-distance,7.section-directions-trip-secondary-text">0.4 mile</div>

  1. Ideally I need a “Travelling Saleman” function which will calculate the best route for a Runner who has several Pick-ups and Drop-offs. The simple version would just put the Pick-ups and Drop-offs in an ordered list (go here, go there, then go there…). The advanced version would add destinations to a custom Google Map or similar.

  2. ALDO. I need to implement a Reputation/History/Feedback system to prevent scammers from just volunteering as Runners then stealing items, or people making Requests when they clearly don’t need the items. For example i) a function for the person making the Offer to give Feedback regarding the Runner (were they pleasant, reliable, trustworthy?), ii) the person making the Request also gives feedback on the Runner but also on the quality of the items provided by the person making the Offer. iii) The Runner also gives feedback regarding the person making the Offer, and the person making the Request iv) A summary or ‘karma score’ based on Number of Offers + Number of Deliveries (‘giving’) : Number of Requests (‘taking’).

  3. ALDO. Once a delivery job is complete (or fails for some reason e.g. the items were stolen by the Runner!), I need a way to add this to the History of i) The person making the Offer; ii) the Runner; iii) The Requester. Then two History views for each User - a public one (a summary without precise details) to help people assess who’s trustworthy; and a private one which only the User themself can see, with full details.

  4. It would be nice to have a “Share this app with a friend button” that emails them a link.

  5. It would be nice to add a “Share feedback, Make a Suggestion, or Share a Bug” button and form, and an easy developer view of everything submitted. Again I saw an Anvil tutorial about this but just haven’t got around to it. Might also need a special “Admin” or “Developer” role in the User database, and/or a Credit List to thank people like yourself who have contributed.

  6. It would be nice to add a “Make donation” button for people who want to donate money to a selected group/cause locally using Anvil’s Stripe Payments service.

PETER. Finally, the task I’m currently working on is a function to call whenever a new Offer or Request is created which will auto-generate Matches. And after that a workflow to confirm i) Offer giver accepts Runner as volunteer for a particular delivery, which releases full address and contact details (email or phone - according to preference of the Offer giver) to the Runner; ii) that items have been collected (Offer giver and Runner both update app); iii) that items have been delivered (Runner and Requester both update app).

If you (or anyone else reading this!) thinks you can help with any of these please just let me know!

All the best,
Peter

for 2 I don’t think you’d need to use custom login flow.

for a quicker turnaround something like…

  • a 2 step login flow
  • add a details entered boolean column to the users table
  • use the anvil login flow to authenticate the email as per normal
  • once email is authenticated by anvil, and they next try to login, they can be redirected if their details have not been entered.
  • once their details have been entered you can then set details entered to True and they can now access the rest of the site.

for 3 if you use anvil login flow you can just use their password reset feature which appears on the login form.

for 5 - assuming you’ve linked datatables to user accounts.

if you want to delete the row or remove the user from a single column in a row

def eradicate_user(user):
  tables_to_remove = ['table_1', 'table_2']
  for table_name in tables_to_remove:
    table = app_tables.get(table_name)
    rows_with_user = table.search(col_with_user=user)
    for row in rows_with_user:
      #option 1 
      row.delete()
      #option 2 
      row[col_with_user] = None

if you want to remove the user from multiple columns in the row

def remove_user_from_multiple_columns(user):
  tables_to_remove = ['table_1', 'table_2']
  columns_with_user = {'table_1': ('col_1', 'col_2'), 'table_2':('col_3',)}
  for table_name in tables_to_remove:
    table = app_tables.get(table_name)
    cols = columns_with_user[table_name]
    query = q.any_of(**{col:user for col in cols})
    rows_with_user = table.search(query)
    for row in rows_with_user:
      for col in cols_with_user:
        if row[col] == user:
          row[col] = None
2 Likes

For point n°1, I think it depends on what type of account you have.
If you have a full Business account, then Anvil should allow 3 developers.
You should somehow be able to register those 3 developers, I don’t know how.
Then, we theoretically should be able to collaborate directly from inside Anvil’s IDE as summarised here https://anvil.works/blog/git-beta-announce.
But that’s quite new land for me too.

Point n.2 and 3 and 5, we can just go with sc549 suggestions.
Point n.4 I can cope with that over the weekend.
Points 6 and 7 sounds more like bells&whistles by now: intersting but not essential.
Points 8 and 9 are important ones, I’ll give them a look too.

I’ll keep you posted.

BR

1 Like

Thanks so much Stu - regarding #3 (Password reset), if they tick “Remember me” then they don’t have a way to get back to the login form unless we explicitly link them to it. Is there a simple function I can link to the button that will bring up the Login form again even if they’re already logged in please?

you could have a signout button (and reduce the number of days for remember me)

def sign_out_button_click(self, **event_args):
  anvil.users.logout()
  # then redirect to login page

2 Likes

Grazie mille, Aldo!

#1: I have a full business account thanks to Meredydd so will try to invite you - I might need your email address by private message please?

Thanks for offering to work on #4, #8, and #9.

I think #6 is actually fairly important because it will highlight to a volunteer those deliveries which are relatively quite short and achievable (either on foot - 1 mile or so - or by vehicle). I’ve updated the requirement above and think there’s an easy solution…

All the best,
Peter

some solutions to #6 here potentially

https://stackoverflow.com/questions/44176381/calculate-road-travel-distance-between-postcodes-zipcodes-python

1 Like

Thanks Stu, this works now albeit with a few more clicks than necessary, ideally:

image

If anyone can tell me what method to call to get to this part of the Forgot Email process directly, please do let me know…

here’s some code i’ve used in the past for changing a password

it uses anvil’s user service to do the brunt work and just catches errors to determine the error message

https://anvil.works/build#clone:LPZTO3QFQRZGVSZY=PGRH7W4A3ER5PQJE7QN5PSJA

with the above app the current password is 'password'

code:

  def save_button_click(self, **event_args):
    """This method is called when the button is clicked"""
    self.current_error.visible = self.new_error.visible = False
    email = anvil.users.get_user()['email']
    op  = self.current_password.text
    np1 = self.new_password_1.text
    np2 = self.new_password_2.text

#ask the user to type their old password and their new password twic
    try:
      anvil.users.login_with_email(email=email, password=op)
      if np1 != np2 :
        raise ValueError("Passwords did not match. Try again.")
      anvil.users.signup_with_email(email=email, password=np1)
  
    except anvil.users.AuthenticationFailed:
      self.current_error.text = 'The password is incorrect'
      self.current_error.visible = True
    except ValueError as e:
      self.new_error.text = e.args[0]
      self.new_error.visible = True
    except anvil.users.PasswordNotAcceptable as e:
      self.new_error.text = e.message
      self.new_error.visible = True
    except anvil.users.UserExists:
      #passed all the other tests
      anvil.server.call('change_password', op, np1)
      self.raise_event('x-close-alert')

the server module then handles the changing of the password:

import bcrypt

@anvil.server.callable
def change_password(op, np):
  user = anvil.users.get_user()
  anvil.users.login_with_email(email=user['email'], password=op)
  try: # just for double checking
    anvil.users.signup_with_email(email=user['email'],password=np)
  except anvil.users.UserExists:
      pass
  user['password_hash'] =  bcrypt.hashpw(np.encode(), bcrypt.gensalt()).decode()
  anvil.users.force_login(user,remember=True)

1 Like

Hi Community,
Now I joined Peter’s organisation for WGACA, how should we proceed “as a team”?
How should Peter let me see the APP?
Peter have you got some administrative tool under the Version Control tab of the app?

Thanks and BR

1 Like

Like this:

1 Like

Many thanks Campopianoa - that arrow is ridiculously small and easy to miss!

I’ll submit a feature request that it gets added to the main and much more obviously Sharing menu:

Hello
is it possible to enable Git Access (beta) as shown on this Meredydd’s post?
I can’t find it in the account I am using to contribute to WAGACA, nor in the APP Peter shared to me.
Or maybe I’m just missing how to use it…

I mean, is this nicely-looking Git client embedded into Anvil’s IDE (that’s the way I understood his post, if so, where is it?) or it is just a GIT client Meredydd used as an example, GIT client that by coincidence has the same appearence of Anvil’s IDE?

BR

Pardon me for playing Devil’s Advocate, but it seems like you’ve made a lovely little smuggling app for aspiring socialists…

Now allow me to play the Devil:

var x = document.getElementById("demo");
function getLocation() {
  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(showPosition);
  } else {
    x.innerHTML = "Geolocation is not supported by this browser.";
  }
}

function showPosition(position) {
  x.innerHTML = "Latitude: " + position.coords.latitude +
  "<br>Longitude: " + position.coords.longitude;
}

Add that into a Script Tag to get the user’s location (x, y) and then send the co-ordinates to a GoogleMap. If you make a custom map tile layer, you could allow users to locate one another…

Link to Google Map Tile Layers: https://developers.google.com/maps/documentation/javascript/layers

1 Like

Thanks for taking the time to comment and suggest code @hjp :grinning:

One of my main reasons for picking Anvil was to keep everything in Python as I’m not a developer by trade and just don’t have the time or head space to learn JavaScript as well.

The Google Maps link was very helpful thanks… currently looking at https://developers.google.com/maps/documentation/maps-static/intro

All the best,
Peter

If you know Python, you know JS. They are very similar, except py is more restrictive (which isn’t a bad thing!).

But, have a look at one of the tools that has saved me many nights of referencing and head scratching:

http://stevs.net/converter/

1 Like

I seem to have maxed out on the number of edits I can make to my task list, so posting this update as new reply:

  1. ALDO @aldo.ercolani and I have been a bit disappointed (or just confused) by the whole Git Clone/YAML/Anvil Clone/shared Business Account collaboration workflow. It seems like the safest but least elegant approach for now is to keep using Anvil’s organic “Share App - Generate a New Clone Link” and manually merge changes. Not ideal. Here’s the latest version for anyone willing to take a look and contribute:
    https://anvil.works/build#clone:P33PVE5OAIUCIJY3=TH42XLEGYI2TOLUOUTEK7QAO
    Also here:
    https://github.com/PFython/WGACA-UK

  2. COMPLETE. Login/Registration process to force users to enter their details and accept Terms of Use.

  3. COMPLETE. Password Reset and Switch User (via Logout)

  4. COMPLETE . Telephone (and Postcode) fields editable from the Data view. All fields editable as part of initial Registration process.

  5. PETER. Function to delete/disable an account and data - thanks @stucork

  6. NOT STARTED Function to estimate the distance between the Offer address and the Request address of a match - perhaps a call to Google Maps or other mapping service.

  7. NOT STARTED Ideally I need a “Travelling Saleman” function which will calculate the best route for a Runner who has several Pick-ups and Drop-offs. The simple version would just put the Pick-ups and Drop-offs in an ordered list (go here, go there, then go there…). The advanced version would add destinations to a custom Google Map or similar.

  8. ALDO. I need to implement a Reputation/History/Feedback system to prevent scammers from just volunteering as Runners then stealing items, or people making Requests when they clearly don’t need the items. For example i) a function for the person making the Offer to give Feedback regarding the Runner (were they pleasant, reliable, trustworthy?), ii) the person making the Request also gives feedback on the Runner but also on the quality of the items provided by the person making the Offer. iii) The Runner also gives feedback regarding the person making the Offer, and the person making the Request iv) A summary or ‘karma score’ based on Number of Offers + Number of Deliveries (‘giving’) : Number of Requests (‘taking’).

  9. ALDO. Once a delivery job is complete (or fails for some reason e.g. the items were stolen by the Runner!), I need a way to add this to the History of i) The person making the Offer; ii) the Runner; iii) The Requester. Then two History views for each User - a public one (a summary without precise details) to help people assess who’s trustworthy; and a private one which only the User themself can see, with full details.

  10. NOT STARTED Nice to have: “Share this app with a friend button” .

  11. NOT STARTED Nice to have: “Share feedback, Make a Suggestion, or Share a Bug” button.

  12. NOT STARTED Nice to have: “Make donation” button.

  13. PETER. Function to auto-generate Matches after a new Offer or Request is created.

  14. PETER. Status tracking: i) Person making Offer accepts Runner as for a particular delivery, which releases address and contact details to the Runner; ii) Items have been collected (Offer giver and Runner both confirm); iii) Items have been delivered (Runner and Requester both confirm).

  15. PETER. Add uniqueness check for Display Names.

My goal is to complete #5, #13, and #14 today (Sunday) and share a Minimum Viable Product with Aldo and others on Monday.