Code Monkey home page Code Monkey logo

mutual-aid-app's Introduction

Development

To contribute to this project, please first register as a volunteer for CHMA here. Make sure to check Technology under Working Groups so we can get in touch with you.

Once you have access to the CHMA Slack, please see DEVELOPING.md to start contributing!


Overview

Functionality walkthrough (dated May 17, 2020)
Technical walkthrough (dated May 17, 2020)

This is an app for doing mutual aid related tasks! It is based on airtable, and requires certain airtable fields. If you already have an airtable, or need help setting this up, feel free to reach out!

Note: this app is severly undertested! it's used in 'production', but development is rapid. YMMV.

The app can provide the following (all optional):

  1. Twilio - Support for a phone hotline that adds to airtable
  2. Slack Bot - Support for a slack bot that can:
    1. Aid in posting info from airtable to slack
    2. Aid in marking airtable from slack
  3. Web app - Supports:
    1. A map that shows open requests
    2. A tool for looking up cross streets + neighborhood zone (not provided) for an address
  4. Reimbursment system - Separate Airtable base that is used to track reimbursements

Moved sections

mutual-aid-app's People

Contributors

alexquick avatar allthesignals avatar caroqliu avatar dannysullivan avatar dependabot[bot] avatar eldilibra avatar ifearcompilererrors avatar jackphelps avatar jconard3 avatar jorganisak avatar jreinlein avatar ksullivan2 avatar mab253 avatar mirandawang avatar mjmaurer avatar piratefsh avatar sandfort avatar sea-witch avatar sephhh avatar zax1133 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mutual-aid-app's Issues

Remove cross streets map link when request has been assigned

What

I added a link to the delivery needed map in this PR #85. We should remove this link and just display the x-streets in regular text once the delivery has been assigned.

Link below should be removed since request is assigned.
Screen Shot 2020-06-09 at 4 04 41 PM

Why

The map no longer works once the delivery has been assigned as it no longer shows up on the map.

Considerations

I marked this as a good first issue if you would like to be contributing the the Slack app regularly. It's a pain to set up for dev, your best bet is watching https://youtube.com/watch?v=b1QW5YNtBaM to set up a local Slack and replace the live app endpoints with the ngrok ones from https://github.com/crownheightsaid/mutual-aid-app/blob/master/src/slackapp/DEVELOPING.md.

Feel free to reach out on #wg_tech on Slack for any issues.

Create requests from emails

The goal here is to have a public email where everything with a particular label gets turned into requests. We're going to use Gmail and labels for the sorting part of the workflow and push all labeled emails into Airtable.

Notes

We talked about it and decided the way to do this with the lowest barrier to entry / fewest moving pieces involves polling the Gmail API periodically. Unfortunately Gmail doesn't have proper webhooks & we want to avoid Zapier as much as possible.

System to poll Airtable for changes

When an intake volunteer marks a Request as "Send to Slack" / "Ready For Aid" it needs to get sent to Slack

Notes

Airflow doesn't have any simple push notifications, but we can poll. This will likely involve creating 2 hidden fields: meta and an auto last_modified column. The last_modified will let the system narrow down the number of rows to examine, and meta will be a hidden json-encoded text column of the last values observed. This way we can tell exactly which fields changed and to what. This is inspired as a generalized version of: https://github.com/bedstuystrong/firebase-functions/blob/master/functions/airtable.js#L78

The internal API could look something like:

const changes = new AirtableChanges(base);
changes.onChange((record, beforeValues, afterValues)=>{
   . . . callback . . .
});
changes.start();

Polling changes could look like:

  1. Get all rows changed since last last_modified (maybe include a jitter or overlap)
  2. Compare each row's non-meta fields vs cached values in meta (json). Filter out rows that have not had any field actually change vs meta
  3. Dispatch change events for the affected fields (could use eventemitter or skip entirely and hard-code the send-to-slack logic for the time being)
  4. Update meta with the current values and save. This means that the row will end up at 1. again unfortunately, but will get filtered out at 2.

Related: #1

Can't upload receipts with airtable forms on mobile

From Slack:

Hi Tech support! I and one other volunteer noticed that we had issues uploading receipt photos to the reimbursement bot form. When asked to select an image it doesn't link to our camera roles or downloads. We both have Android phones and are wondering if that is the common denominator? I have just emailed my self the photos and then posted the receipt from my computer instead of phone. Any idea as to why this is happening? Thanks!

We should investigate and maybe consider a new solution if its not possible with airtable!

Display for cluster deliveries with a unique color marker

What

We are currently not showing deliveries marked for cluster deliveries on https://crownheightsma.herokuapp.com/delivery-needed. They should be color coded and differentiable from the other deliveries, maybe even have an option to toggle them.

Why

To help cluster delivery folks out. They are currently using the google maps view in Airtable, which has limitations. There will likely be requests for future features, but for a start, just start showing them on the map.

Create /neighborhood-finder view without header for Airtable block use

Problem

The Neighborhood Finder map https://crownheightsma.herokuapp.com/neighborhood-finder is used in the Airtable as a block, which appears as below:

Initial view
Screen Shot 2020-05-29 at 3 55 15 PM

Users will have to scroll in that block to see the address field and block.

Scrolled down:
Screen Shot 2020-05-29 at 3 55 23 PM

Suggested solution

Can we create a URL param e.g. ?minimal_view=true that makes the address field and map visible in the Airtable block, and moves it to below the map? For intake volunteers, I don't think it's super important for the title and desc to be visible if they are already familiar with the tool.

Permissions needed

  • access to intake Airtable, or just create a block with the map in staging Airtable. it should show up the same either way.

Link to delivery-needed map from Slack app message

What

Screen Shot 2020-05-22 at 3 36 50 PM

Cross street info on Slack request post (as highlighted above) should link to https://crownheightsma.herokuapp.com/delivery-needed?request=<REQUEST CODE>

Why

This makes it easier for volunteers to quickly look up the location of the request + makes the map easier to get to.

Dependencies

This should happen after #77 is completed as cluster deliveries get posted to Slack but are not available on the map right now.

Add ability to edit delivery bot posts

The templated delivery bot posts are unable to be edited through slack natively. We should add a shortcut to slack to make the posts editable. This can use the same/similar UI as what creates the posts in the first place.

4-char Request Code has conflicts

so we have almost 10000 requests in airtable(!) and we are starting to get overlap with request code. Request code is the last four characters of airtable's unique Id. @mab253 suggested just upping that to last 6 characters. I'm going to look into how this would affect backend, and if we could do this in-place

Display informational message on page when there are no deliveries to display

What

Display an info alert banner in top of ClusterMap when there are no deliveries available to display.
https://github.com/crownheightsaid/mutual-aid-app/blob/master/src/webapp/components/ClusterMap.js#L38

Example of an alert banner atop map:
Screen Shot 2020-05-15 at 5 36 08 PM

Dependencies

To avoid merge conflict, allow this PR to be merged first #71 as it introduces the alert banner.

Why

Slack context: https://crownheightsmutualaid.slack.com/archives/C010AUQ6DFD/p1590158599155100
We do not display deliveries that aren't posted on Slack yet or are marked for driving clusters. Sometimes this displays an empty map and is confusing for volunteers

Slack bot should send scheduled summary messages of requests that are dragging

The #community-needs channel can get overwhelming, so we can teach the bot how to post a scheduled summary message to bump the requests that are dragging.

BSS does this and it rules, so we can ape their design (big ups @maybejustmaybe & @cubeghost)
image
implemented here: https://github.com/bedstuystrong/firebase-functions/blob/899d2e15c0bf651c02702adb9ae983e25f517997/functions/messages.js#L143

  • It should include any requests in the "Delivery Needed" status that are not assigned to a cluster delivery already.
  • Since our data model doesn't emphasize priority we can use the time since it was first posted to prioritize requests.[1]
  • Maybe as a reach the bot can pin the messages itself?

[1] Or should it use the time since the request was created in the first place?

Slack bot should join public channels by default

Wanted to avoid this scope because I thought it gave permission for private channels as well. Looks like that's not the case.

Otherwise, as I experienced today, if the slack bot token changes, you have to manually add the bot to all channels it was in.

Auto add neighborhood info to airtable

This should introduce two new things in the address page:

  1. Field for Request Code that should be clearly marked as optional (expects code as in the Requests airtable ex: KSDF)
  2. Button at the end for adding the info to the Request airtable

license?

am I correct that the code is currently unlicensed/public domain and therefor not currently definable as Open Source or Free Software?
unlike some of your other code, this does not show a license (see image)

please make the license explicit so others know what their rights are (and you define yours)

remember that the origin of Free Software licenses is the fact that unlicensed code can be taken by someone and re-released under a proprietary license that could deny you any right to do further development your own code
Screen Shot 2020-06-12 at 8 54 56 PM

make strings translatable

Going to have a hard time getting some groups I know to use this unless the core interface can be in something other than english (based on each user's choice)

Integrate with nycma

Been chatting with Saje, and she can send us requests that they get for neighborhoods of our choosing.

where are config variables stored?

I'm having trouble getting the mapbox stuff to work, can someone tell me where I'd find the values that were entered in the heroku interface on setup? is that in a file somewhere? in a db? where do I look to make sure it's correct?

Handle 500 result of googleGeoClient call

As a developer, if the GoogleGeoClient call returns a 500, I want to know what the error is so that I can efficiently debug my setup.

Here's where we call this: https://github.com/crownheightsaid/mutual-aid-app/blob/master/src/api/neighborhood-finder/get-address-meta.js#L19

Expected behavior: Google returns a 500. The error message is printed to the console.
Actual behavior: Google returns a 500. This is not caught by the try/catch block and instead the error thrown is

TypeError: Cannot read property 'geometry' of undefined
    at exports.addressHandler (mutual-aid-app/src/api/neighborhood-finder/get-address-meta.js:38:9)

please add some comments to your code

new to javascript, can't make any sense of the code. A few comments to explain what is happening where would make the code much more usable and sharable.

Add table view for delivery needed map

What

Add a table/list view of requests to https://crownheightsma.herokuapp.com/delivery-needed with the same information available on Slack.

Why

Delivery Needed Map (DNM) only has a map view right now. This was intended to augment the slack app requests so volunteers can browse for open requests by location.

It would be better to also have a table view of requests so volunteers can do all the browsing on the DNM page. The popovers only show minimal information (first name, x-streets and request code).

They still have to sign up for the request on Slack, but hopefully this makes less back and forth.

Considerations

  • I don't have designs yet, but if you are up for it, you can draft something up
  • Hovering/clicking on marker on the map should highlight the table/list entry somehow. And vice versa. Kind of like how the yelp map view works.
  • Add ability to filter and search could be a second iteration feature.
  • We average about 30-50 requests so there is no pagination at the moment. Might wanna consider what might happen if we have more requests.

Volunteer lookup should be case insensitive

We had an issue where the case didn't match between the Volunteers table and slack so the delivery workflows were erroring out.

Email addresses are not strictly case insensitive, though it seems like most mail services are[1]. I think the best course of action is to make findVolunteerByEmail case-insensitive (and possibly trim/otherwise normalize).

related:
https://github.com/crownheightsaid/mutual-aid-app/blob/master/src/airtable.js#L136
https://community.airtable.com/t/ignoring-case-in-filter-by-formula/12594

[1] The RFC says only that the local-part (think part before the @) MAY be case-sensitive and I haven't ever encountered one that was. It is /so/ much more likely that someone entered their email in different cases across these two systems than two separate people have the same email with different cases that I think we are very safe.

allow intake volunteers to delete a request and post it again

right now it seems that if an intake volunteer posts in the wrong channel, or they need to start over with a post rather than edit it, the Slack app won't let them delete and re-post. The corresponding code won't appear when they click the lightning bolt to "Post Open Request" - so they only get to post the request once.

** i was able to fix this manually for someone in the Airtable by deleting the slack_ts and slack_channel in the "Meta" field in Airtable ... a good place to start?

Add zone map to app

Preferably client side so they can used a cache version of the webapp and it will work if the backend is down

Problem with twilio links in airtable for Firefox users

the urls that are pushed into the airtable with a link to the twilio message do not work in Firefox. the url needs to have .mp3 (or .wav) appended to it for it to work in all browsers.
the current urls lead to an unusable text file being downloaded
image

Can't post to slack with > 10 open requests

Slack will send invalid_arguments if you try to create a option list in a view with more than 10 options.

This can happen if someone has more than 10 open requests (open here meaning not Dispatch Started or Delivery needed and not posted in slack). This is a more common occurrence because clustered deliveries aren't posted in slack.

Solution: don't return clustered deliveries in Post Open Request selection.

Script for adding volunteer to a slack usergroup

Volunteer's have a "Help you can offer" field they fill out: https://airtable.com/shraIzCNdiMwW1bpP

If we added the volunteers to usergroups, we could @ large swaths really fast: https://slack.com/help/articles/212906697-Create-a-user-group

We should have the following usergroups to start:
@ cars
@ bikers
@ financialsupport

See here for a shitty backfill example I wrote at 1am: https://github.com/crownheightsaid/mutual-aid-app/blob/master/scripts/backfillSlackId.js

Canonicalize / dedupe Volunteer records

Multiple Volunteer records may exist with the same email

We need a way to encourage picking a "canonical" volunteer record when intake vols are assigning requests to themselves. Otherwise, requests may be assigned to multiple records which makes it hard to handle

When we lookupByEmail, we just pick the first record. Canonical volunteer for a given email should be the one created first


Another solution would be to restrict duplicate emails in airtable, but I see no way to do this

Remove/Centralize Airtable field names

Continued from: #10 (comment)

We're trying to come up with a way to avoid a bunch of hard-coded Airtable column name strings. It would be nice if we could come up with a way to do something similar with Airtable select values too.

Maybe we should just KISS and export an object out of the Airtable module?

requestFields = {
   requestId: "Request ID",
   status: "Status"
}
. . .  elsewhere . . .
record.get(requestFields.requestId)
  • If we wanted... the opposite of KISS ... we could play around with wrapping the airtable client to return real types. Right now .find()/select() return Airtable Record instances. We could make a class for each table that maps the fields together and wrap the airtable constructor to have find()/select() return those concrete types correctly. While that does sound like a fun programming exercise I'm not certain it's worth it.

Refactor directory structure

Things are starting to settle, and we're sticking with monorepo. Here are proposed changes for the src/ dir.

  • /webapp
    This stays the same.
  • /slackapp
    Contains the endpoints that the slack app needs to operate (interactivity and events)
  • /workers
    Cron-like logic that will be run every X minutes
  • /api
    Any endpoints we need that may be used by webapp, workers, or slack
  • airtableapi.js
    Shared airtable access with schema
  • slackapi.js
    Helper for Slack web API (https://api.slack.com/methods)
  • constants.js
    Organization names and such
  • middleware.js
    Non slack-only express middleware. Maybe should live in /api?
  • index.js
    Unfortunately Create React App needs this here for now

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.