Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Submission Jie and Myron #3

Open
wants to merge 105 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
105 commits
Select commit Hold shift + click to select a range
1b821a3
Set up file structure 1
Leejere Oct 23, 2022
0a61d6c
list-loader & CSS
Leejere Oct 24, 2022
dd5d0cc
correction
Leejere Oct 24, 2022
480c529
correction
Leejere Oct 24, 2022
d1de4f0
data structure
Leejere Oct 24, 2022
56d3df4
Formatting
Leejere Oct 27, 2022
cd1df25
change formatting
Leejere Oct 30, 2022
d4bc3ce
update
Leejere Oct 30, 2022
60d373b
search box filter
myronbanez Oct 30, 2022
276d2e5
Merge branch 'main2' of https://github.com/Leejere/js-voter-canvassin…
myronbanez Oct 30, 2022
0f96d5d
voter list function
myronbanez Oct 30, 2022
9a4a700
voter list complete and search box in progress
myronbanez Oct 30, 2022
5513b47
attempt at search box and removing former search filter
myronbanez Oct 30, 2022
0d123cf
adjusted search box
myronbanez Nov 2, 2022
f3ebcc8
test local storage
Leejere Nov 2, 2022
50ceef4
fixed voter data
Leejere Nov 2, 2022
6294ec8
Merge branch 'musa-611-fall-2022:main' into main2
Leejere Nov 2, 2022
41df7a6
finished search box
myronbanez Nov 3, 2022
2af955a
update
Leejere Nov 5, 2022
e299893
Merge branch 'musa-611-fall-2022:main' into dev
Leejere Nov 5, 2022
ed992eb
make list-loader readable; fulfilling 2 requirements
Leejere Nov 5, 2022
40a89b2
update voter list to fulfill requirement
Leejere Nov 5, 2022
be8a715
load list automatically from based on local storage
Leejere Nov 5, 2022
a5ea744
make voter list grouped by address
Leejere Nov 5, 2022
0556067
update voter list grouped by address
Leejere Nov 5, 2022
26a6b5a
highlight list item when selected
Leejere Nov 5, 2022
6aeb2c7
update voter list; still on button CSS
Leejere Nov 5, 2022
2024e02
draft finished - voter list icons
Leejere Nov 6, 2022
8e75730
search also by address; enable multi-word search
Leejere Nov 6, 2022
8c28de2
load 0101 automatically if not specified
Leejere Nov 7, 2022
4051271
fixed a bug
Leejere Nov 7, 2022
581dcc0
adjust zoom bounds to fit viewport, because of the existence of voter…
Leejere Nov 7, 2022
cce1196
finish highlight voter system
Leejere Nov 7, 2022
e613dbd
search box filter also applied to map markers
Leejere Nov 7, 2022
846b48f
reorganize all filters
Leejere Nov 7, 2022
7a69df1
fixed a bug in selected-voters.js
Leejere Nov 7, 2022
8899d57
Made voter list item scrolled to view when selected
Leejere Nov 7, 2022
3c93e83
Made voter scrolled to view in list & change class name to comply wit…
Leejere Nov 7, 2022
e0942e0
Made every building a map marker, instead of every voter
Leejere Nov 7, 2022
0af7429
Used simpler way to highlight marker
Leejere Nov 7, 2022
1a13c64
make voter list expand longer & make CSS more readable
Leejere Nov 7, 2022
b1758a5
Only show expand button when necessary
Leejere Nov 7, 2022
e0267d2
Initiated README
Leejere Nov 7, 2022
760eb20
updated README as of 1107
Leejere Nov 7, 2022
e621ee6
scroll back to top when updating list
Leejere Nov 7, 2022
76791de
update README
Leejere Nov 7, 2022
6a28fed
annotate some CSS
Leejere Nov 7, 2022
a11eb6b
added filter window
Leejere Nov 7, 2022
9721508
hide whole searchbox and list when clicking on button
Leejere Nov 9, 2022
133c8de
pan to voter on map when selected
Leejere Nov 9, 2022
c54c83b
load list on enter key
Leejere Nov 9, 2022
a9d5d1e
add comments, overall descriptions of js scripts
Leejere Nov 9, 2022
813b53f
filter buttons
myronbanez Nov 11, 2022
775166e
used firestore to save and load list number
Leejere Nov 11, 2022
4ae97d5
Merge branch 'dev' of https://github.com/Leejere/js-voter-canvassing …
Leejere Nov 11, 2022
5cc0898
filter
myronbanez Nov 11, 2022
68007a7
modified pointer event so map can be clicked when search box is hidden
Leejere Nov 12, 2022
194ae0b
changed to mapbox
Leejere Nov 12, 2022
d9b0d9b
filters
myronbanez Nov 12, 2022
971db73
Merge branch 'dev' of https://github.com/Leejere/js-voter-canvassing …
myronbanez Nov 12, 2022
edde442
finished filters
myronbanez Nov 12, 2022
7ec5101
made scroll list function reusable
Leejere Nov 12, 2022
7074dd7
Merge branch 'dev' of https://github.com/Leejere/js-voter-canvassing …
Leejere Nov 12, 2022
c8778f7
cleaned up filters
myronbanez Nov 12, 2022
3548800
Merge branch 'dev' of https://github.com/Leejere/js-voter-canvassing …
myronbanez Nov 12, 2022
97429af
transition between normal and edit mode
Leejere Nov 12, 2022
5455044
Merge branch 'dev' of https://github.com/Leejere/js-voter-canvassing …
Leejere Nov 12, 2022
86615d8
update data based on cloud storage right after loading
Leejere Nov 13, 2022
5ec3088
finished voter history
Leejere Nov 13, 2022
536f673
started basic info panel
Leejere Nov 13, 2022
21e4b5e
finished canvas status part
Leejere Nov 13, 2022
92d1f03
optimized update-status
Leejere Nov 14, 2022
6898509
finished edit page wireframe
Leejere Nov 14, 2022
c50b62e
display language finished
Leejere Nov 14, 2022
ad98ad2
finished final save button
Leejere Nov 14, 2022
a1e2a56
fixed a bug
Leejere Nov 15, 2022
b4afd4f
fixed filters and css
myronbanez Nov 15, 2022
c060ef8
Merge branch 'dev' of https://github.com/Leejere/js-voter-canvassing …
myronbanez Nov 15, 2022
dba35b3
created a new function for visit status
myronbanez Nov 15, 2022
1804589
finished recorder
Leejere Nov 15, 2022
4fa1d3d
Merge branch 'dev' of https://github.com/Leejere/js-voter-canvassing …
Leejere Nov 15, 2022
c9beab3
finished basically
Leejere Nov 15, 2022
4ffc8c4
small change
Leejere Nov 15, 2022
93549ac
small change
Leejere Nov 15, 2022
2e56476
small changes
Leejere Nov 15, 2022
3989e68
trying a fix
Leejere Nov 15, 2022
466d38b
fix
Leejere Nov 15, 2022
2d4f895
trial fix
Leejere Nov 15, 2022
5022060
test map
Leejere Nov 16, 2022
6538197
Fixed bottom viewport block problem; clear input box when clicking on…
Leejere Nov 16, 2022
e753b55
finished filters
Leejere Nov 16, 2022
bc5b955
filter transition
Leejere Nov 16, 2022
76c8f8c
change filter button color when filter applied
Leejere Nov 16, 2022
c3e1ba2
minor changes
Leejere Nov 16, 2022
5a5c596
tested layout
Leejere Nov 17, 2022
0590e1d
tested layout
Leejere Nov 17, 2022
09fcf68
fixed problem
Leejere Nov 17, 2022
41b50e9
slight changes on list loader height
Leejere Nov 17, 2022
bec211a
finished filter CSS
Leejere Nov 17, 2022
bc17ec8
minor changes
Leejere Nov 17, 2022
3714f22
minor changes on layout
Leejere Nov 17, 2022
5647d2e
minor fix
Leejere Nov 18, 2022
93ce3e9
changed button cursor style
Leejere Nov 21, 2022
5010d68
Finished Readme
Leejere Nov 21, 2022
acd1ad4
minor changes
Leejere Nov 21, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 125 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,126 @@
# Voter Canvassing App
# **Canvassers**

Team members:
* ...
* ...
## Visit the app [here](https://leejere.github.io/js-voter-canvassing/site/)
[![face](mockups/saved_iphone13blue_landscape.png)](https://leejere.github.io/js-voter-canvassing/site/)

by **Jie Li ([@Leejere](https://github.com/Leejere))** and **Myron Bañez ([@myronbanez](https://github.com/myronbanez))**


This is a mobile-friendly web-app used for voter canvassing. With this app, the canvasser can select the voters from a list and a map, view their status and other information, and record additional information regarding each canvassed voter. The more specific [**PRD for this product**](https://github.com/Leejere/js-voter-canvassing/blob/dev/PRD.md) can be found in the same repository or via [**this link**](https://github.com/Leejere/js-voter-canvassing/blob/dev/PRD.md). The PRD was produced by Mjumbe Poe ([@mjumbewu](https://github.com/mjumbewu))

## **Data source**

The voter data comes from [Pennsylvania Department of State](https://www.dos.pa.gov/VotingElections/OtherServicesEvents/VotingElectionStatistics/Pages/VotingElectionStatistics.aspx), who provides voter registration data that includes the name, address, and other voting-related information. The data is available for purchase through [this link](https://www.pavoterservices.pa.gov/Pages/PurchasePAFULLVoterExport.aspx). For this application, only data from Philadelphia gets extracted, preprocessed, and geocoded by Mjumbe Poe ([@mjumbewu](https://github.com/mjumbewu)).

## **App Modules**

### **Module 0: Database APIs**

Data from the [Pennsylvania Department of State](https://www.dos.pa.gov/VotingElections/OtherServicesEvents/VotingElectionStatistics/Pages/VotingElectionStatistics.aspx) is stored in the same repo under the directory of `\data\voter-lists\`. Due to its large amount, the data is split into more 1,000 separate lists by neighborhood, which also acts as task lists for the canvassing team. One single list will be loaded at a time on demand in the next module.

At the same, the requirement document asks for the function of recording and saving additional information. This app uses [**Firebase**](https://firebase.google.com/docs/firestore) to store additional information recorded on canvassing visits. The saving and loading API calls are in the script of `main.js`.

### **Module 1: `list-loader`**

Each voter list can get loaded into the app asynchronously on demand via the `list-loader` widget. `list-loader.js` primarily deals with loading data. The loaded data gets stored in a global object, which is the data source for all other operations. The `list-loader` module is rerequisit for all other functions of the app.

- **Default list on page load.** By default, the same list that the user last used on their device is loaded. When the user last loaded the list, the list number was stored in `localStorage` and also on Firebase. On page load, the app first seeks `localStorage` for the previous list number. If such `localStorage` does not exist, the app makes an API call to Firebase and pulls the list number there. If both do not exist, **the first list (0101)** is loaded by default.

- **Custom list input widget** An input box exists on the top right of the viewport that allows the user to input a number, and then imports the corresponding list. The list loader is triggered either on **button click** or on **Enter keypress**.

- **Two API calls to the repo and Firebase.** When the loader is triggered, an API call is made to fetch voter data. On success, another API call is made to Firebase to pull down additional information recorded on previous canvassing visits. The Firebase database is organized by list number, so only data regarding this list is loaded.

- **Data update and display.** The data pulled from Firebase is used to update the data pulled from the repo. Then, the updated data is passed to **Module 2**.

Showcase:

| Number input | Data loaded |
|--|--|
| ![loader-1](mockups/list-loader-before_iphone13blue_portrait.png)| ![loader-2](mockups/list-loader-after_iphone13blue_portrait.png)|


### **Module 2: `list-filters`**

This filter filters voters after a particular voter list is loaded by name/address, registered party, voter status, and visit status. The kernel script for the function resides in `list-filters.js`. The filters work together in the following way:

1. **Data import.**
2. **Event listeners.** Event listeners get added to all filter widgets.
3. **Filter application.** Every time a filter event is recorded, whether a new filter is applied, or a filter is modified or canceled, the `allFilters` functions takes the imported data and applies **all the filters** to produce to filtered version of the data.
4. **Display update.** Use the filtered data to updated the voter list and map, which gets implemented in the **Module 3**.

Showcase:

| Filter window | Data filtered |
|--|--|
|![filter-1](mockups/filter-1_iphone13blue_portrait.png)|![filter-2](mockups/filter-2_iphone13blue_portrait.png)|


### **Module 3: Voters display**

This model displayed either comprehensive or filtered voter data in a particular list in the voter list and on the map.

- `voter-list.js` takes the data, group them by address, and display them in a list. The list includes the voter's address, full name, and some icons that shows the voters canvassing status (pending visit, visited, awaiting followup, etc.), voter status (active or inactive), party registration, etc.

- `map.js` takes the data, makes an geometry object (`FeatureCollection`), and display it on the map. Note that **every marker stands for one address** (house number + street name), rather than one voter.

Each displayed voter either on the map and on the list is attached with an event listener, ready to be selected in **Module 4**.

### **Module 4: Voter selection**

This module highlights a **maximum of one voter** as the "selected" voter. The module resides in `selected-voter.js` and contains the following components:

- A global variable to store the ID of the currently selected voter. If no voter is currently under selection, the variable remains `undefined`.
- Event listeners added on each voter list item and map marker. Note that as each map marker stands for an address rather than a voter, **the first voter by this address** is selected when the marker is clicked on.
- Whenever the list item or marker get clicked, it either
- **highlights a new voter**,
- **updats the highlighted voter**, or
- **unhighlights the currently highlighted voter**.
- The highlighted voter ID is recorded and passed into **Module 5**.

### **Module 5: Voter information display**

When a voter is currently highlighted, the most basic basic information regarding this voter is displayed on the bottom panel: name, address, visit status, and other information that was recorded on the previous visit (if any).

- **Basic information**: name and address.
- **Visit status**: either `pending`, `awaits followup`, or `completed`. This information is pulled from Firebase, and every voter is `pending` by default.
- **Other overview information**, e.g., registered party, whether received mail ballot, etc. Some of this information was recorded on the last visit and pulled from Firebase.

An Edit button exist on top of the basic-information panel. On click, the filters and voter list is hidden, and more information panels emerge.

- **Record panel**: displays voter information recorded on the last visit, if any. The user may record, edit, and save information on this panel via **Module 6**.
- **Voting history panel**: displays the past voting records of the selected voter. The list may expand on demand.

Showcase:

|Basic panel|Record panel|Voting history|
|-|-|-|
|![display-1](mockups/display-1_iphone13blue_portrait.png)|![display-2](mockups/display-2_iphone13blue_portrait.png)|![display-3](mockups/display-3_iphone13blue_portrait.png)|

### **Module 6: Data editing and saving**

The user may edit information via the "Update Status" button on the basic-information panel and the "Save" button on the record panel.

- The "Update Status" button only saves visit statuses, whereas the "Save" button saves all information.
- Whenever the user clicks a button or inputs some text, the unsaved edits will be temporarily recorded in the corresponding DOM object. When the save buttons are clicked, the unsaved chagnes get consolidated and uploaded to Firebase.
- A "toast" appears on the button to give feedback to the user that the information has been saved.

Showcase:

| Update Status | Final Save |
|-|-|
|![save-1](mockups/status-saved_iphone13blue_portrait.png)|![save-2](mockups/saved_iphone13blue_portrait.png)|

## Collaboration

|Item|Contributor|
|--|--|
|Wireframing| Myron & Jie|
|Module 0: Firebase| Jie |
|Module 1: List loader| Jie|
|Module 1: Parsing CSVs| Myron|
|Module 2: List filters | Jie & Myron|
|Module 3: Voters display | Jie & Myron|
|Module 4: Voter selection| Jie|
|Module 5: Voter information display| Jie|
|Module 6: Data editing and saving| Jie|
|CSS|Jie & Myron|
Binary file added mockups/display-1_iphone13blue_portrait.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added mockups/display-2_iphone13blue_portrait.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added mockups/display-3_iphone13blue_portrait.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added mockups/filter-1_iphone13blue_portrait.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added mockups/filter-2_iphone13blue_portrait.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added mockups/raw/display-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added mockups/raw/display-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added mockups/raw/display-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added mockups/raw/filter-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added mockups/raw/filter-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added mockups/raw/list-loader-after.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added mockups/raw/list-loader-before.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added mockups/raw/saved.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added mockups/raw/status-saved.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added mockups/saved_iphone13blue_landscape.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added mockups/saved_iphone13blue_portrait.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added mockups/status-saved_iphone13blue_portrait.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading