Coder Social home page Coder Social logo

findthemasks / findthemasks Goto Github PK

View Code? Open in Web Editor NEW
54.0 54.0 40.0 23.43 MB

All the code for findthemasks.com.

Home Page: https://findthemasks.com

License: MIT License

JavaScript 44.21% Shell 0.04% Dockerfile 0.02% Python 0.64% SCSS 18.96% Handlebars 36.13%

findthemasks's Introduction

findthemasks.com

Build Status

This repo hosts the code for findthemasks.com which also provides an embeddable map to other projects

New volunteer?

Join the slack! https://join.slack.com/t/findthemasks/shared_invite/zt-ejpx15bn-6H7K51xGCWp7FEXMn1nQqw

  • new dev? please look at issues and comment on something to grab it!
  • new data moderator? Join the slack and come to #data!
  • not either? Say hello on Slack and check out open roles for our team here: https://findthemasks.com/volunteer

Current setup

  • The website reads from a Google sheet, generates a json blob, which is rendered by a Node server.

Reading our data to build your own frontend

  • Our curated data file updates every five minutes and can be read from https://findthemasks.com/data-us.json [US]. Each country that we serve has its own country code, i.e. data-ca.json for Canada, data-fr.json for France, etc.
  • Similarly, we also offer CSV output at http://findthemasks.com/data-us.csv , with similar country-code modifications for each country.
  • If reading in data and producing web output sounds like a lot to do, please read on:

How can I embed your map on my site?

We'd love for anyone to embed our map to help fight the battle against coronavirus. Please go here for detailed instructions: https://github.com/findthemasks/findthemasks/wiki/Embedding-%23findthemasks-donation-sites-page

Adding Countries and Locales

We use virtual paths via routing rules on the server to view country-specific datasets.

For example, /us/give.html will filter the map to the United States and /fr/give.html will filter to France.

To view translated version of a country you can pass in a locale parameter. /us/give.html?locale=fr-FR will show the map of the United States in French and /fr/give.html?locale=en-US will show the map of France in English.

To add a new country, you need to set a few variables.

  1. Get the country code from https://www.iban.com/country-codes.
  2. Add the country code and a link to the donation form to viewHelpers/getDonationFormUrl.js. The form should include translations for all official languages in that country.
  3. Add the translated strings for all official languages in that country in i18n.js. As a starting point, it is OK to launch a new language using an international variant. e.g. you can launch Canada with en translations and fr translations, they do not need to be localized to en-CA and fr-CA.
  4. Update the list of languages and countries in countries.js and locales.js and ensure that they propagate correctly to the language and country dropdowns. In countries.js you should also add the name of the string for that country's administrative region. e.g. US = "State", CA "Province", FR = "Department", copy for who they should direct large donations to, and copy for who they should contact if there are no donation sites near them.

Data inflow, storage & moderation

Intake

Currently information about PPE needs is contributed by members of the public through a Google Form. We have at least one form per country; for CA and CH we have one per language. See the International Forms and Data section of the Wiki for details.

Storage

Currently the data about PPE needs is stored in Google Sheets spreadsheets (one per country). Data from the forms (described above) automatically feeds into these sheets. See International Forms and Data section of the Wiki for details.

Moderation

Moderation is done by volunteers in accordance with the guidance laid out in the findthemasks wiki.

Directory structure

  • /public - The client-side code for the website.
  • /functions - The cloud function used to generate data.json. Not needed for frontend work.

Firebase

Basic architecture

Firebase is used to pull data from our moderated datastore and then generate a data.json. There is a production environment findthemasks and a dev environment findthemasks-dev.

The setup uses cloud functions to provide http endpoints, cloud-storage to keep the generated results, and the firebase realtime database (NOT firestore) to cache oauth tokens.

Adding an oauth token requires hitting the /authgoogleapi?sheetid=longstring on the cloud-function endpoint and granting an OAuth token for a user that has access to the sheet.

How to deploy

  • Install the firebase cli for your platform.
  • Do once
    • firebase login
    • firebase use --add findthemasks-dev
    • firebase use --add findthemasks
    • cd functions; npm install # Note you need node v8 or higher. Look a nvm
  • Switch deployment envrionments firebase use [findthemasks or findthemasks-dev]
  • Deploy the cloud function. cd functions; npm run deploy

How to set config variables.

Secrets and configs not checked into github are specified via cloud function configs.

To set a config:

firebase functions:config:set findthemasks.geocode_key="some_client_id"

In code, this can be retrieved via:

functions.config().findthemasks.geocode_key

In get all configs:

firebase functions:config:get

The namespace can be anything. Add new configs to the findthemasks namespace.

How to locally develop

Firebase comes with a local emulation environment that lets you live develop against localhost. Since we are using firebase configs, first we have to snag the configs from the environment. Do that with:

firebase functions:config:get > .runtimeconfig.json

Next generate a new Firebase Admin SDK private key here: https://console.firebase.google.com/project/findthemasks-dev/settings/serviceaccounts/adminsdk

And save it to service_key.json

Then start up the emulator. Note this will talk to the production firebase database (likely okay as the firebase database is just storing oauth tokens).

export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service_key.json
firebase emulators:start --only functions

This will create localhost versions of everything. Cloud functions should be on http://localhost:5001 and console.log() messages will stream to the terminal.

There is also a "shell"

firebase functions:shell

that can be used, but running the emulator and hitting with a web browser is often easier in our simple case.

Scripts that edit the spreadsheet (Apps Script)

There are currently 2 scripts that automatically update the spreadsheet, and one that backs it up:

  • fillInGeocodes: fills in the lat/lng column based on the address in the "address" column. (Note that the "address" column is defined as the column that has "address" in row 2.) Uses Google Maps geocoding API. Currently runs once/minute.
  • createStandardAddress: fills in the "address" column based on the data in the "orig_address", "city", and "state" columns. Uses Google Maps geocoding API. Currently runs once/minute.
  • backupSheet: makes a timestamped copy of the sheet. Currently runs once every 2 hours.

There are a few important things to know about these scripts:

  • They are visible by navigating to tools > script editor from the Google Sheet.
  • They can be run by anyone who has edit permission to the Google Sheet.
  • Triggers (automation) can be set up by navigating to Edit > Edit current project's triggers.
  • The dev-owner of each sheet should set up a trigger for each of the 3 scripts. (US spreadsheet dev owner is @susanashlock's gmail).
  • The scripts are run using quota of the user the user that runs them.
  • Each Gmail user has a fixed amount of geocoding quota per day. This quota is somewhere around 250 calls per day. @susanashlock's account has 'special' quota. We're not sure exactly what it is, but is sufficient to support about 1000 calls per day.

Frontend development

To work on the frontend, you'll need to run a development server.

Install npm

On mac, brew install npm

Install dependencies

npm install

You'll need to do this once when first setting up, and periodically as dependencies change. The dev server script (see next section) will crap out with an error message when a new dependency is added - this is your cue to run 'npm install' again.

Run the dev server

npm run dev

This should start a server running on http://localhost:3000

Thanks

findthemasks's People

Contributors

4kbt avatar alex avatar awong-chromium avatar awong-dev avatar cjimmy avatar crayne avatar csakoda avatar ctavispost avatar dependabot[bot] avatar devops-corgi avatar dhruv4 avatar drwestco avatar ezanmoto avatar graemer avatar krithin avatar linderr avatar lizhaoqi99 avatar nburt avatar ngottlieb avatar patricknelson avatar r-pop avatar raindrift avatar saikatbhadra avatar sikakkar avatar smattingly avatar stephmarisa avatar susanashlock avatar tinabeans avatar volantwish avatar zhuochenwang 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  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  avatar  avatar  avatar  avatar  avatar

findthemasks's Issues

Add contact info row

It would be good to have a contact info row so people could contact the hospitals with questions (i.e. one I've been asking lately is "do you accept 3D printed masks or face shields?"). Even if it was optional, as I'm sure hospitals are way too busy right now to answer a lot of questions.

How does a hospital turn off the flow of masks?

If too many people show up/obstruct operations or cause trouble somehow, how do we shut off the flow of people quickly?

The contact email at the bottom of the page is a good start, but is there anything further we can do, so that @r-pop doesn't need to be awake at all-hours?

Fix formatting on mobile

Chrome 80 Android

The "how to donate" list numerals are elided

Some of the line breaks aren't rendering

Add open box general guidance to site

Guidance via PPE distro zoom meeting of projects similar to this one. This could go at the top of the donation sites list, right before the JS section:

If you are donating open packages, please put them in a ziploc bag with a note saying whether they have been used, whether anyone in your household has been sick or travelled outside the country, and the expiration date if known.

Small jump in vertical scroll on first filter-tap, chrome-android

There is a small jump in vertical scroll position on chrome-android the first time I tap on a filter after page load (new site, as of 14:06 Pacific , March 21).

Steps to repro:

  1. Open site (Pixel 3a, chrome 80.0, Android 10)
  2. Scroll down to filters, with filters near bottom of screen
  3. Tap a filter (FL works).

Expected:
Filter filters results below

Happens:
Vertical scroll jumps by ~0.5-1 screen upward
Filter filters results below.

THE GREAT DATA BACKFILL

Hello volunteers! This need is short term and appropriate for detail-oriented folks without coding experience. We are moving to an automatic publishing pipeline that relies on our google form directly to build the site, but we currently have a lot of valuable listings on the site that didn't go through the form at all. We have to put this info into the form so that we don't lose it in the move.

Between now and mid-day Saturday March 21, the task is:

  1. Comment here to claim a state and let others know not to start on it.
  2. Read through the live findthemasks.com site section for your state
  3. For each hospital, check if it is in our sheet already (use ctrl-F to search): https://docs.google.com/spreadsheets/d/1GwP7Ly6iaqgcms0T80QGCNW4y2gJ7tzVND2CktFqnXM/edit?usp=sharing
  4. If it is not there, submit it through our public google form: https://docs.google.com/forms/d/e/1FAIpQLSfgCpK5coPVFC6rJrE7ZhimiZuDoEaL6fo6gYqxsN_FIpJZhg/viewform

That's it!

Encourage form submitters to link to the recipient's own instructions

Recently I learned about Seattle Children's request for donations from a local nurse. I know they've edited that post at least two times, slightly revising what they are willing to accept and drop-off location options. It would be great if this URL was linked under Seattle Children's so everyone could verify the latest information with minimal communication overhead.

More generally, encouraging form submissions to include links like this could help keep all the information current. The field for

Drop off instructions, eg curbside procedure or mailing address ATTN: instructions:

could include something like this:

(recommended: link to their public request where information is kept updated)

Available donation sites not appearing

When I got to the site and scroll down to see the hospital/donation site locations, none appear.

Browser: Google Chrome Version 80.0.3987.122 (Official Build) (64-bit)
OS: MacOS Mojave Version 10.14.6

Screen Shot 2020-03-21 at 6 32 36 PM

Add related resources section or subpage

Have gotten many suggestions to post two related categories of resources:

How to donate masks if you are a business or institution with a large supply, this org can coordinate your donation to highest need within WA: https://www.suppliessaveliveswa.org/

Various grassroots efforts to sew masks. Our site should stay focused on finding certified PPE, but ok to link to these resources for the crafters.

Basic github project hygiene

I haven't run a github project before and I know I've skipped some steps. If someone has this experience and wants to take on the rest of project setup and dev process, in consultation with me and the major contributors, it's probably time to do that.

Tracking or credit for donors

Idea that was emailed in: If there is a way to track and share who donated, that might be good incentive for people to donate. I've been working with local dental societies to ask dentists to donate PPE. But dentists are struggling now, some laying off employees, and PPE is valuable. Some free marketing for people who donate might help them!

Filter items could be more clear?

At present, filter titles are as follows:

"n95s", "masks", "face shields", "booties", "goggles", "gloves", "kleenex", "sanitizer", "overalls", "gowns", "respirators".

Suggest:

"N95 masks/respirators", "surgical masks", "face shields", "medical booties", "safety goggles", "gloves", "kleenex", "hand-sanitizer", "medical overalls", "gowns", "advanced respirators (PAPR/CAPR/etc.)".

In location filter, scroll to list after state selection

Do we see the need for a user to select multiple states before scrolling?
If not, we should auto-scroll to the list as soon as they select a state. In mobile, it's not obvious what clicking on a state does because the list is beyond the end of the screen.

initial information architecture and nav

"I'm a citizen seeing this on twitter and I want to know what the site is about before I lose ttention"

"I'm a citizen with a possible stash of PPE and just want to know what to do next"

"I'm a healthcare provider/organizer and need to update info"

Need to automate new donation site workflow

Current workflow:

  • receive gform
  • call hospital if info is incomplete (it usually is)
  • manually edit index.html, push, and deploy

Better ideas:

  • automatic update from form (but I really worry about moderation - people have put in long random comments, lots about mask sewing which is not what we're doing with this site)
  • publish form responses as google sheet and make viewable (but also need a moderation step if possible - is it?)
  • streamlining of the current workflow that would scale to a larger number of less technical volunteers without high potential for mistakes in prod

Scale responses to contact@

Right now, [email protected] is set up as a dreamhost fwd only email address pointing at my personal email. I would like to figure out better handling for email as traffic grows.

I've observed these types of incoming email:

  1. Data additions, updates, and takedowns. These should go to the data moderation team. If they could end up posted in the "#data" slack, then people could say they're on it and when they're done. And hopefully trigger a reply back to let the person know - but that's not p0. It would be equivalent to automatically reply "Thank you, we'll get this up ASAP!" on receipt. (note: right now I often ask people emailing to submit the form themselves, but I also have a lot of new volunteers chomping at the bit for tasks, and form entry would be a great fit for new folks)
  2. Offers to sell us masks, or questions about retooling a factory to make masks. This is awesome to see but our project isn't set up to handle it. I forward these to our friends at [email protected] (https://pg.gl) who are able to consider and fund shipments of masks.
  3. Offers to collaborate, which core contributors should continue to handle manually (eg could scale from just me to me and a few others, but can't be a ruleset)
  4. Press inquiries. Not many so far but could be more in coming days.

Ideas on what to improve here?

Stand up basic monitoring

Would like to be alerted if the site goes down, the list of donation locations does not show up, or (stretch goal) one of the data fields stops populating.

Extended url-text causes horizontal-scrollability on chrome-android

With the new version of the site (1406 Pacific, March 21), when viewing on Chrome-android (pixel 3a), the site can be scrolled laterally.

It appears that long url strings are the cause. Firefox-android does not do this.

This bug may be addressed in the future by collapsing the urls back into links.

Add embedded map view

API costs:
Geocoding API to convert addresses to lat/long: 0.005 USD per call
Google Maps JS API per map load cost: 0.0056 USD per load (at 100,001 - 500,000 monthly volume)

We can call the geocoding API once per new form entry as part of the backend conversion to JSON. Let's say 200 hospitals. This cost would be negligible ($1)

Current requests to the page is ~40k after 1 day of release. Assuming traffic is ~500,000 map loads per month. Cost would be $2,800.

Automate importing from other PPE projects

The PPE distribution cross-project slack is in agreement that job 1 is to start importing data from each other. I have communicated this to all of them:

Ok, we are still working on how to unblock sending data into findthemasks.com - our eng likely need to help with integrations. but to get our data out via code, please read from http://findthemasks.com/data.json . This is the moderated subset of our sheet. It updates every 5 minutes.

I would like us to start importing from others. Top pri is https://docs.google.com/spreadsheets/d/1txEanDkIrJ5GNfSk-zlXkTlB-bQPNRN_Y69qEwmdme8/htmlview?fbclid=IwAR1A6TrHCQ9TttNJbb1kB6b2Xot4DCem-z6DVXUR4V5qToUboOr-50D7h6g&sle=true#

Yesterday @cchang-adi did a huge manual import, but ongoing import is needed. Would like an engineer to pick up this task.

If someone can also represent us in the cross-project import/export chatter and help unblock others who want to send us data, that would be ideal.

Vnext prelaunch checklist

  • Ensure a change in form data percolates
  • Ensure the stylesheet is named something OTHER than style.css and style1.css to avoid month-long caching crazy
  • Open incognito tab. Pop open web inspector and go to "networks" tab. Open the page. Check the Response headers for all of index.html, stylesheet, etc., and ensure that the cache-control max-age does not look insane.

Structuring New York City boroughs

Thinking about marking the cities for the NYC boroughs as

New York - Bronx
New York - Brooklyn
New York - Manhattan
New York - Queens
New York - Staten Island

That'll place the alphabetization into more-traditional order within NYS.

Ok to munge that way?

Not all N95s are equal

Earlier this week Seattle Children's request for donations said for 3M N95 masks they were accepting "1860, 1860s, and 1870". My unused 3M N95s from when the wildfire smoke was bad are the 8511 model.

I'm unclear whether any hospitals or clinics claiming to accept N95s will accept 8511 or any of the other models which aren't marketed for medical use. I want to donate the small number of masks I have directly to a reputable place where HCWs will use them, but at the same time I want to do it without contributing to communication bandwidth overload (see also #81).

Currently the Google Form has a checkbox for "N95s", but it could help to be more precise or at least encourage clarification in an open-ended field.

Next steps on adding a map

Looks like there are a few steps required to make a map happen, based on investigations with @susanashlock last night:

Geocoding: In order to place map pins, geocodes/lat-lons are required. The hospital locations are static, so there are a few different options. Here are some of them:

  1. We geocode as the data come in, at the form-level or by hand into the Google Sheet.
  2. We have the json-building backend make geocode calls to Google Maps, based on the Google Sheet's address field, and populate a new json field with lat-lons.
  3. We have the clients pull the geocodes, based on the json address field.

My current guess is that 2 is the right one, but we might require care not to exceed the API's query rate (10/second?). 1 has a trivial number of API calls, 3 would generate oodles.

Maps API:

  1. Should we acquire a findthemasks-specific API key?
  2. Before going live with a map, we need to estimate API usage and secure sufficient credits.

I think @susanashlock's prototype map layout, merged last night, will be quick for the js-wrangling devs to integrate/lay-out once we can address the issues above.

site only mentions N95 masks but P95 is same or better

N95 means it captures 95% of particles, N means not for oil particulates. P95 means resistant to oil particulates, R95 means somewhat resistant to oil particulates, so P > R > N, if you have a P95, R95, or N95, those are needed, it's not just N.

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.