Disaster Response SJ is a React based web application that notifies people of active disaster information for San Jose and includes disaster planning resources, plus an administrative interface for disaster response managers to create/maintain active disaster updates.
src
directory.If you've never used GitHub before, here's a Git/GitHub tutorial to help you get started.
Read more in the How to Contribute section.
You'll need to setup the frontend (the interface you interact with on the browser) and the backend (the mock server containing disaster data) before you can run the web app.
node -v
and npm -v
python
You'll need to run the following on the command line.
git clone https://github.com/codeforsanjose/disaster-response-sj.git
. This should download the project to your computer in a directory called disaster-response-sj.git checkout develop
while in the disaster-response sj directory.npm i
. These are programs and files the project requires to run.npm i nodemon -g
. This restarts the server whenever you make changes to the code.projectInfoData.js
from project lead on disaster-response-sj Slack channel or click: https://codeforsanjose.slack.com/archives/C77546YF6/p1555038461000900projectInfoData.js
into config
directory in your disaster-response-sj repo to enable the back end.Issues installing? See Troubleshooting section.
npm run all
should start the backend and frontend, then automatically open a tab in your web browser with the web app. If the tab doesn't open, you can manually enter http://localhost:3000 in your browser to view the app.You should be greeted with the app homepage.
nodemon --exec babel-node server.js
or alternatively npm run server
.
Let it finish launching before starting the frontend. Manually restart the server with the comand rs
npm start
.
You'll need to do this in another command window.Skip ahead to the Developer Documentation section.
npm run all
is just an alias to run the manual commands. If on Windows and that command doesn't work, you can try npm run win-all
. To stop running the app, you can hit Ctrl + C in a Windows command prompt and it'll ask to terminate running jobs.
Either way, you should land on the main page showing active disaster posts with tab navigation options and a header reading Disaster Response SJ.
This part of the app is aimed at public citizens.
You can create disaster posts or update existing disaster posts from the administrative part of the app, which requires a login. You might also want to do development on this part of the app.
To access, go to http://localhost:3000/login
You will need a username and password to login to the admin area. Contact the project lead for the login credentials: https://codeforsanjose.slack.com/messages/disaster-response-sj
This part of the app is aimed at government employees.
Some developers may run into issues installing and running the app on their local machine. There have been some reported issues getting the app to run on Windows.
A long thread containing information on the issues can be found here.
Run the following as an administrator. Any command line windows should be specifically ran as an administrator.
git clone https://github.com/codeforsanjose/disaster-response-sj.git
npm install -g --production windows-build-tools@4.0.0
npm install bcrypt --save
npm install react --save
npm i
npm install -g nodemon
npm install -g @babel/core @babel/cli @babel/node
git checkout develop
in the disaster-response sj directory.nodemon --exec babel-node server.js
while in project directorynpm start
npm list <package name to check>
to see if they show up.npm i
againQuestions? Reach out to the project team on the #disaster-response-sj Slack channel https://codeforsanjose.slack.com/messages/disaster-response-sj
Running this web app and working on it assumes some level of command line knowledge, familiarity with git, and using npm. If you're unfamiliar with this, you may want to review some web development resources. You can also ask for some guidance from other contributors.
Project Leader:
Inspired by civic tech volunteer responses to hurricanes Harvey and Irma, the goal of the disaster-response-sj project is to engage with San Jose's Office of Emergency Services to discuss how Code for San Jose can contribute to disaster response and planning.
If you aren't sure how your skills can support the project, talk to other contributors and they can help you find suitable work.
Ask to be added as a collaborator to the disaster-response-sj repo if you want to add branches on the main repo. You'll need to provide your GitHub name.
Many contributors will just clone the main repo to their local machine for development instead of forking.
It's more complicated to manage than pushing branches directly to the main repo, but if you want your own copy of the main repo on GitHub under your GitHub account, you can fork it. It's more effort in syncing updates/making pull requests, but you get full control over your own forked repo. You can also create a pull request right away without waiting to be added as a collaborator.
develop
branch: git checkout develop
then git checkout -b name-of-your-new-branch-here
.git push origin name-of-the-branch
.develop
branch so it can be reviewed by team members. Share it in the Slack channel.develop
branch if everything looks goodMore Resources:
Sometimes you'll work on a feature branch for a while and during that time someone else will merge updates into the main develop branch of the GitHub repo. The local copy of the develop branch on your computer won't be updated with those changes. When you already have several commits and go to create a pull request to merge your changes into the main repository, it's more likely you'll have merge conflicts to resolve.
You can prevent those conflicts by first merging in the updated version of the main repository with your local copy before you create a pull request. You'll need to either stash or commit any uncommitted changes before you rebase.
There's 2 ways to do this: by merging or by rebasing.
Rebasing can help preserve a cleaner commit history for a project. For example, if you and a dev named Jane added commits to the develop branch, rebasing is like adding your changes on top of what John has already done.
To rebase:
// gets the upstream changes from the origin
git fetch
// switch to your feature branch if not already on it
git checkout your-feature-branch-name
// rebases changes from the origin develop branch onto the local develop branch
git rebase origin/develop
If you forked the repo, you'll also need to push the new develop branch to your fork before creating your pull request git push -f fork-origin-name-here develop
You'll do most frontend interface development work in the /src
directory.
This app uses React as a front end framework, with the basic project set up using Create React App.
Notice that /src
has several directories, though we'll focus on 3 in particular:
disaster-response-sj
| ...
|_src
| ...
|_components
|_compositions
|_containers
| ...
Most important are the /components
, /compositions
, and /containers
directories, which are the 3 general categories of interface blocks inspired by the Atomic Design philosophy used in the project:
Small components for things like form input fields, the logo, and Open Street Maps elements. These are the smallest interface pieces a user can interact with. How small is a component supposed to be? It's a bit of a judgment call, but they should generally be something small with a single purpose--like an interface button or tooltip box. If you're going to reuse it across the interface, it should be small enough to be reusable. If interactive, it should contain just the pieces that frequently change so that the rest of the interface doesn't need to get rerendered every time.
You can think of these like different kinds of individual Lego bricks (and if you've never played with Legos before, it's a kind of interconnecting building block toy).
Note that even though only this directory is specifically named "components", compositions and containers are also React components. They just use the lower level components as building blocks in their own component code.
These use the lower level components in addition to adding their own specific logic and code to compose more complicated interface pieces. You can imagine it as using different individual Lego pieces to build a larger model.
Contains the majority of the interface blocks, with compositions for the main disaster posts tab (/DisasterPosts
), the preparing for disaster tab (/FEMAChecklist
), and the after a disaster tab (/InfomationalResources
). The admin area (/AdminForm
) and login (/Login
) tabs are also here.
There's also blocks for smaller parts of the interface like the detailed view for a clicked disaster post that shows in a modal popup (/DisasterModalPostDetails
) and the HTML markup for each disaster post (/PostMarkup
) that gets used in both the disaster posts tab plus the admin area.
Contains the layout for the largest interface blocks, essentially the overall admin area and the public part of the app.
You can think of these like separate pages. Continuing our Lego analogy, this is like arranging each of the models into a complete scene or cityscape.
Every level of React component, whether component, composition, or container, has a common directory structure or way that it is organized. Here's an example using the MapDisplay component. Notice how the directory and files within share names:
MapDisplay
|_MapDisplay.css
|_MapDisplay.js
|_MapDisplay.test.js
|_mapPin.png
Thus, if you want to add a new component, you would follow the same basic file structure. The directory has the name of the component and the js and css files share the name.
There are other modules that make up the project which don't fit in the previously defined categories. Some files and directories are denoted as markup. These contain detailed HTML elements for JSX render functions to use.
There is also:
If you want to apply styles to just a single component, you can add styles to the css file in that component's directory and it will apply to the component generated by the js file. This organization pattern makes the styles more modular so they apply specifically to the relevant component.
Note that component styles have a kind of namespacing applied to prevent styles for one component from conflicting with styles that have the same name in other components. This is achieved through the descendant CSS selector. When adding CSS, you'll want to maintain that qualified selector to prevent conflicts:
/* For the AdminContainer component, notice the parent class added before every other style definition */
.AdminContainer {
}
.AdminContainer .admin-tabs {
display: grid;
grid-template-columns: 1fr 1fr;
border-bottom: 1px solid #ccc;
}
.AdminContainer .tab-item {
cursor: pointer;
border-right: 1px solid #ccc;
padding: 0.5em;
}
If we look at the previous MapDisplay component example and wanted to add some CSS styles, we would add it to the CSS file in the MapDisplay directory:
MapDisplay
|_MapDisplay.css <------ ADD YOUR STYLES HERE
|_MapDisplay.js
|_MapDisplay.test.js
|_mapPin.png
What if you have a CSS style that you want to apply to multiple components on a page?
You would simply add that CSS to the parent component's css file so it gets applied to the child components. So if you had a Button component and a Map component that were both used in a Composition component called MapTab, and wanted both Button and Map to have the same background color, you would add the background color style in MapTab's css file so it applies to both components that are used in the MapTab:
MapTab (Renders a Button and a Map)
|_MapTab.css <------ ADD YOUR STYLES HERE
|_MapTab.js
Button
|_Button.css
|_Button.js
Map
|_Map.css
|_Map.js
Static assets/files for a component should be placed in the same directory as the component it is used in, keeping components modular.
To load a static file like an image in your component, you'll need to import it at the top of your js file, which gives you the path as a string, and then use it in the render function where you need it:
// We're in the Logo component file Logo.js
import React, { Fragment } from 'react'
import logoImg from './logo-dark-bg-web.png'
...
// Somewhere in your rendering function
<img className="logo-img" src={ logoImg alt="logo"} />
...
You can read more on importing static files here.
There are different ways to write a React component. You can read more about the basics of creating a component here..
When you create a component, organize your files to match the existing project structure. That means creating and labeling your component directory and your component files with the component name and separating the JS and CSS files:
ComponentName
|_ComponentName.css
|_ComponentName.js
You should also think about how to classify your component and place it in the appropriate directory: components, compositions, or containers.
Read about how you can write your components using React Hooks here, for a more modern approach that matches the current project direction.
Frontend routing is handled by React Router for navigating between the main app container, the admin container, and the login component. These can be viewed in Navigation/Navigation.js
.
Routing is a way of providing bookmarkable URLs for certain app components or rendered configurations, so someone could type in www.someappname.com/login
and the React app would know to load the login component in the main container instead of sending the user to the main page component.
Backend development work can be done in the /backend
directory and server.js
.
The app uses mongoDB for the database and Express as a server side framework for Node.js. It also uses Passport for authentication and bcrypt for password hashing.
/config
- the projectInfoData.js
file contains credentials that lets the app connect to mongoDB servers to load the app database. There is currently no local mongoDB database set up./backend
contains stuff related to routing, the database, and authentication, and some utilities.server.js
manages most of the interaction between the front end and back end. It also contains some Twilio API interactions for sending disaster posts.This project uses React hooks, which is a newer, cleaner way of writing a React app versus the more traditional class style. In some places, you may see the older style of React methods used. These are good candidates for refactoring to use React hooks.
Here's an example of equivalent components written in each style:
// React Hooks style
import React, { useState } from 'react';
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
// React Classes style
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
Some resources to learn more about React hooks:
via @mthong:
City Council video and documentation
Agenda items 3.5, 3.6 and 3.7 all relate to the flood response and future emergency management. I’d specifically recommend watching/listening to the City staff presentation and public comment (go to item 3.5 in the video index), or reading the staff memo for item 3.6.
See particularly Sec. 3.6 Memorandum; it's 130 pages total (!!) but the TL;DR is Appendix B and C.
^^ Comprehensive collection of relevant tools and organizations
note to self: add to KB https://www.projectptolemy.co https://disastersystems.org
Willow's shelter needs flow chart
The Humanitarian Data Exchange
example local Emergency Response
https://www.youtube.com/watch?v=m9aa7xqX67c https://mozilla.github.io/server-side-tls/ssl-config-generator/
Make sure that you update the security group rules on AWS to include 443 connections in addition to 80
`server { listen 80 default_server; listen [::]:80 default_server;
return 301 https://$host$request_uri;
} server { listen 443 ssl; server_name disaster-response.codeforsanjose.com;
ssl_certificate /etc/letsencrypt.../full.pem;
ssl_certificate_key /etc/letsencrypt.../priv.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
ssl_prefer_server_ciphers on;`
This project is open source software licensed under the MIT License. Here's a short description from choosealicense.com:
A short and simple permissive license with conditions only requiring preservation of copyright and license notices. Licensed works, modifications, and larger works may be distributed under different terms and without source code.