City Voice provides a way for citizens to submit issues (e.g. graffiti, a streetlight is out) and receive status updates from the city. It is written in JavaScript using Node, Express, Mongoose, and React. It implements (and augments) the Open311 specification, and is under the direction of Daniel Zappala of BYU.
- issue reporting with geolocation and image submission
- adminstrative geo-visualization of issues, filtering, searching
- Node JSON API
Install Node.js and MongoDB (make sure it is running: run mongo
in the terminal, and then version()
. If Mongo is running, you will get a version number). After that, run this in your terminal:
git clone https://github.com/byu-osl/city-issue-server.git && cd city-issue-server
Install your dependencies using npm (this may take a minute or two, and may require using sudo):
npm install
sudo npm install -g supervisor
Start the server:
npm start
npm start
uses node-supervisor to watch your files and restart when you r files change. You can now hit the homepage at http://localhost:3000/.
You can load some dummy data into the database using utility/load-demo-requests.js
The entry point of the application is App.js. Dependencies are resolved using Webpack (which also does the ES6 transpilation). You can use webpack -d --watch
to automatically rebuild when your files change.
This project also uses JSXHint. Every JS/JSX file should pass JSXHint.
After that, submit a pull request. Thanks for helping out! Feel free to submit an issue for any confusion you might have.
Ranked by priority:
- admin/users: add users, change roles
- permissions server/client-side
- sign in / sign out
The main server files are server.js and app.js. The business logic is mostly contained in the routes directory.
├── app.js // entry point for the server. ├── client-side // all public, client-side files │ ├── bundle.js // built by webpack │ ├── css // more global css (most styling in jsx) │ ├── images // app images │ ├── index.html // main and only html file │ ├── js │ │ ├── admin │ │ │ ├── AdminMap.js // map on the admin page │ │ │ ├── AdminNav.js // left navigation/filtering │ │ │ ├── AdminPage.js // body of admin page │ │ │ ├── RequestFilters.js // to filter requests │ │ │ ├── Requests.js // shows when "requests" is selected │ │ │ ├── Services.js // shows when "services" is selected │ │ │ └── Users.js // shows when "users" is selected │ │ ├── App.js // main client-side file. Includes routes. │ │ ├── components // commonly used throughout the app │ │ ├── HomePage.js // hit at / │ │ ├── individual-request // details on single request │ │ ├── mixins │ │ │ └── mapMixin.js │ │ ├── Navbar.js // shows on every page at the top │ │ ├── request-form // main issue request form │ │ └── utility │ │ ├── global.js // ran when the app starts │ │ ├── _.js // underscore.js │ │ ├── server-api.js // talks to server/caches data │ ├── vendor // 3rd party libs ├── config.js // server config ├── models // mongoose models │ ├── request.js │ ├── service.js │ └── user.js ├── notes │ ├── 311spec.txt // used as a checklist │ ├── CI analysis.md // contextual inquiry results │ ├── contextual inquiry.md │ ├── LICENSE │ ├── Notes.md │ └── screenshot.png // used in this readme ├── package.json ├── README.md ├── routes // node routes ├── server.js // initial server creation ├── start.sh // ran in "npm start" ├── test │ └── test.js // test file ├── uploads // user uploads └── utility
Here is a overview of how you might add a field to the issue request form. Starting server-side:
- For this feature, you need to make changes in requestsHandler.js, and the request model.
- Add the field you want to the issue request schema.
- Add any validation logic in saveRequest().
- Write a React component for that portion of the form. This is where your HTML will go.
- Create a new file, and follow the pattern of the other components of the form. Make sure to write a getter to expose state to the parent component (avoid using jQuery to interact with the DOM as much as possible).
- Head over to the client-side app.js. The entry point for the request form is here.
require
the component you made at the top of the file, and add a reference to it in therender
function of the form. - In RequestForm's
submitForm
, get the new field, and add it to the POST request.
If you need help, submit an issue.