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

Expand UI functionality #4

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Binary file added app/assets/images/nittany_lion_photo.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 removed app/assets/images/ossoff_photo.png
Binary file not shown.
8 changes: 4 additions & 4 deletions app/assets/stylesheets/application.scss
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ nav {
max-height: 100%;
}

#ossoff-photo {
#nittany-lion-photo {
/* TODO: resize and optimize photo */
background-image: image-url('ossoff_photo.png');
background-image: image-url('nittany_lion_photo.png');
position: absolute;
bottom: 0;
right: 0;
Expand Down Expand Up @@ -215,7 +215,7 @@ canvas#confetti-canvas {
}

@media only screen and (max-width: 1024px) {
#ossoff-photo {
#nittany-lion-photo {
width: 40%;
}
.hero #user-name {
Expand All @@ -224,7 +224,7 @@ canvas#confetti-canvas {
}

@media only screen and (max-width: 768px) {
#ossoff-photo {
#nittany-lion-photo {
display: none;
}
form#login-form .control.phone-number, form#login-form .input {
Expand Down
11 changes: 2 additions & 9 deletions app/controllers/relationships_controller.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
class RelationshipsController < ApplicationController
def index
# to_a calls
@contacts = current_user.non_self_voters.order(:tier, :sos_id).load
@secondary_contacts = current_user.secondary_network.order(:tier, :sos_id).load

@contacted_size = (@contacts + @secondary_contacts).count { |v| !v.not_yet_called? }
@tier_4_size = (@contacts + @secondary_contacts).count { |v| v.tier == 4 }

@contacts = @contacts.reject { |v| v.tier == 4 }
@secondary_contacts = @secondary_contacts.reject { |v| v.tier == 4 }
@contacts = current_user.non_self_voters.order(:reach_id).load
@contacted_size = (@contacts).count { |v| !v.not_yet_called? }
end
end
15 changes: 8 additions & 7 deletions app/controllers/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,17 @@ def set_client
end

def start_verification(to, channel='sms')
return # unless Rails.env.production?
channel = 'sms' unless ['sms', 'voice'].include? channel
verification = @client.verify.services(ENV['VERIFICATION_SID'])
.verifications
.create(:to => '+1' + to, :channel => channel)
verification.sid
unless Rails.env.development?
channel = 'sms' unless ['sms', 'voice'].include? channel
verification = @client.verify.services(ENV['VERIFICATION_SID'])
.verifications
.create(:to => '+1' + to, :channel => channel)
verification.sid
end
end

def check_verification(phone, code)
return true # unless Rails.env.production?
return true if Rails.env.development?
begin
verification_check = @client.verify.services(ENV['VERIFICATION_SID'])
.verification_checks
Expand Down
54 changes: 22 additions & 32 deletions app/controllers/voter_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def show
def next
call_list = current_user.call_list
voters_seen = current_user.seen_voters
next_voter = call_list.find { |v| !voters_seen[v.sos_id.to_s] }
next_voter = call_list.find { |v| !voters_seen[v.reach_id] }

if params[:skip] && voter
record_in_reach(Rails.configuration.reach.responses[:skip])
Expand All @@ -41,36 +41,35 @@ def next
end

def update
if params[:last_call_status]
if voter_params[:last_call_status]
current_user.log_call!
if voter.update(last_call_status: params[:last_call_status])
record_in_reach(Rails.configuration.reach.responses.to_h.fetch(params[:last_call_status].to_sym))
calls_logged = current_user.calls_logged
if Rails.configuration.rewards.videos.key?(calls_logged.to_s)
flash[:success] = Rails.configuration.rewards.messages[:success]
flash[:confetti] = true
flash[:video] = REWARD_VIDEOS[calls_logged]
elsif calls_logged == 1
flash[:success] = Rails.configuration.rewards.messages[:first]
flash[:confetti] = true
else
flash[:success] = 'Call status updated, check out the next voter to call!'
end
# TODO: un-comment this if we want to sync responses to the Reach API
# record_in_reach(Rails.configuration.reach.responses.to_h.fetch(params[:last_call_status].to_sym))
end

if voter.update(voter_params)
flash[:error] = "Error saving changes, try again"

# if last_call_status is what changed, we want to redirect to the next
# voter. Else we just want to reload the previous voter
if voter_params[:last_call_status]
flash[:success] = 'Contact status updated, check out the next voter to call!'
redirect_to voter_next_path
else
flash[:danger] = 'Error updating call status, try clicking again!'
redirect_to voter_next_path
flash[:success] = 'Changes saved successfully'
end
elsif params[:is_needs_a_ride_form]
needs_a_ride = params[:needs_a_ride] == "1"
record_in_reach(Rails.configuration.reach.responses[:needs_a_ride]) if needs_a_ride
voter.update(needs_a_ride: needs_a_ride)
else
flash[:danger] = 'Error recording changes, try again!'
redirect_to @voter
end
end

private

def voter_params
params.require(:voter).permit(:email, :last_call_status, :voter_registration_status, :notes)
end

def migrate_voters_seen
if current_user && session[:voters_seen].is_a?(Hash)
current_user.set_voters!(session[:voters_seen])
Expand All @@ -84,17 +83,8 @@ def voter

def authorize_and_set_contact
return unless voter.relationships.where(user: current_user).empty?
same_household_voter = voter.
household_members.
where(sos_id: current_user.relationships.select(:voter_sos_id)).
first

if same_household_voter
@same_household_voter = same_household_voter
else
flash[:danger] = "You don't have access to that voter's details"
redirect_back(fallback_location: root_path)
end
flash[:danger] = "You don't have access to that voter's details"
redirect_back(fallback_location: root_path)
end

def record_in_reach(choice_id)
Expand Down
40 changes: 40 additions & 0 deletions app/lib/pa_sos_loader.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# frozen_string_literal: true

# Load data from the tab-separated PA secretary of state data
class PaSosLoader
VOTER_FILE_LOCATION = ENV['PA_SOS_VOTER_FILE']

def load_voters
to_upsert = []

# PA SOS data is a tab-separated file with the format
# StateVoterID/unknown/LastName/FirstName/MiddleName/Suffix/Gender/DOB/DateRegistered/ActiveorInactive/Not Sure what this date is--might be updated reg?/PartyRegistration/House Number/Apt/StreetName/City/State/Zip/
data = File.readlines(VOTER_FILE_LOCATION)
data.each do |line|
sos_id, _, last_name, first_name, middle_name, _suffix, gender, _dob,\
_date_registered, _is_active, _, _party, house_number, \
apartment_number, street_name, _, _, city, state, zip = \
line.split("\t").
map { |col_data| col_data.start_with?("\"") ? col_data[1...-1] : col_data } # strip surrounding quotes

voting_street_address = "#{house_number} #{street_name}"
if apartment_number.present?
voting_street_address += " ##{apartment_number}"
end

voter_data = {
sos_id: sos_id,
first_name: first_name,
last_name: last_name,
middle_name: middle_name,
gender: gender,
voting_city: city,
voting_zip: zip,
voting_street_address: voting_street_address,
}
to_upsert << voter_data
end

Voter.upsert_all(to_upsert, unique_by: nil)
end
end
76 changes: 76 additions & 0 deletions app/lib/reach_csv_loader.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# frozen_string_literal: true
require 'csv'

class ReachCsvLoader
VOTER_FILE_LOCATION = ENV['REACH_VOTER_FILE']
USER_FILE_LOCATION = ENV['REACH_USER_FILE']
RELATIONSHIP_FILE_LOCATION = ENV['REACH_RELATIONSHIP_FILE']

def load_voters
to_upsert = []

::CSV.foreach(VOTER_FILE_LOCATION, headers: true) do |row|
address_line_1 = row["Address Line 1"]
address_line_2 = row["Address Line 2"]

address = "#{address_line_1}#{address_line_2 ? ", #{address_line_2}" : ""}"

to_upsert << {
reach_id: row["Reach ID"],
sos_id: row["State File ID"],
voter_data_status: row["Source Tag"] == "Voter" ? :reach_match : :unmatched,
voter_registration_status: row["Source Tag"] == "Voter" ? :registered_in_district : nil,
first_name: row["First Name"],
prefix: row["Prefix"],
last_name: row["Last Name"],
middle_name: row["Middle Name"],
suffix: row["Suffix"],
phone_country_code: row["Phone Country Code"],
primary_phone_number: row["Phone Number"],
email: row["Email"],
voting_street_address: address,
voting_zip: row["Zip"],
voting_state: row["State"],
voting_city: row["City"],
support_score: row["Support Score"],
created_at: Time.now,
updated_at: Time.now,
}
end

!Voter.upsert_all(to_upsert, unique_by: nil)
end

def load_users
to_upsert = []

::CSV.foreach(USER_FILE_LOCATION, headers: true) do |row|
to_upsert << {
first_name: row["First Name"],
last_name: row["Last Name"],
id: row["User ID"],
phone_number: row["Phone Number"],
email_address: row["Email Address"],
created_at: Time.now,
updated_at: Time.now,
}
end

!User.upsert_all(to_upsert, unique_by: nil)
end

def load_relationships
to_upsert = []
::CSV.foreach(RELATIONSHIP_FILE_LOCATION, headers: true) do |row|
to_upsert << {
user_id: row["User ID"],
voter_reach_id: row["Reach ID"],
relationship: row["Relationship Type"],
created_at: Time.now,
updated_at: Time.now,
}
end

!Relationship.upsert_all(to_upsert, unique_by: [:user_id, :voter_reach_id])
end
end
2 changes: 1 addition & 1 deletion app/models/relationship.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
class Relationship < ApplicationRecord
belongs_to :voter, class_name: 'Voter', foreign_key: 'voter_sos_id'
belongs_to :voter, class_name: 'Voter', foreign_key: 'voter_reach_id'
belongs_to :user
end
33 changes: 7 additions & 26 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,11 @@ def display_name
end

def call_list
relationship_call_list + household_member_call_list
relationship_call_list
end

def non_self_voters
Voter.where(sos_id: Relationship.where(user_id: id).where.not(relationship: 'Me').select(:voter_sos_id))
end

def secondary_network
Voter.
where(household_id: voters.select(:household_id)).
where.
not(sos_id: voters.select(:sos_id))
Voter.where(reach_id: Relationship.where(user_id: id).where.not(relationship: 'Me').select(:voter_reach_id))
end

def calls_logged
Expand Down Expand Up @@ -64,9 +57,9 @@ def seen_voters
{}
end

def log_voter!(sos_id)
def log_voter!(reach_id)
seen = seen_voters
seen[sos_id] = true
seen[reach_id] = true
set_voters!(seen)
end

Expand All @@ -79,20 +72,8 @@ def set_voters!(voter_hash)

def relationship_call_list
Voter.
where(sos_id: Relationship.where(user_id: id).where.not(relationship: 'Me').select(:voter_sos_id)).
order(:tier, :sos_id).
where(last_call_status: [:not_yet_called, :should_call_again]).
where.
not(tier: 4)
end

def household_member_call_list
secondary_network.
order(:tier, :sos_id).
where(last_call_status: [:not_yet_called, :should_call_again]).
where.
not(tier: 4).
where.
not(sos_id: relationship_call_list.select(:sos_id))
where(reach_id: Relationship.where(user_id: id).where.not(relationship: 'Me').select(:voter_reach_id)).
order(:reach_id).
where(last_call_status: [:not_yet_called, :should_call_again])
end
end
Loading