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

Fix naming bug #5

Open
wants to merge 22 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
63 changes: 63 additions & 0 deletions app/controllers/imports_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
class ImportsController < ApplicationController
before_action :require_admin

def index
end

def create
successful_uploads = []
failed_uploads = []

loader = ReachCsvLoader.new

if params[:users_file]
was_success = !loader.load_users(from: params[:users_file].tempfile)
if was_success
successful_uploads += ["Users"]
else
failed_uploads += ["Users"]
end
end

if params[:voters_file]
was_success = !loader.load_voters(from: params[:voters_file].tempfile)
if was_success
successful_uploads += ["Voters"]
else
failed_uploads += ["Voters"]
end
end

if params[:relationships_file]
was_success = !loader.load_relationships(from: params[:relationships_file].tempfile)
if was_success
successful_uploads += ["Relationships"]
else
failed_uploads += ["Relationships"]
end
end

if (successful_uploads + failed_uploads).empty?
flash[:warning] = "No uploads processed"
end

if failed_uploads.any?
flash[:danger] = "Got errors handing import of: #{failed_uploads.join(", ")}. Please check the app logs."
end

if successful_uploads.any?
flash[:success] = "Successfully imported: #{successful_uploads.join(", ")}"
end

redirect_to imports_path
end

private

def require_admin
unless current_user.is_admin
flash[:danger] = 'You are not authorized to view that page'
redirect_to relationships_path
end
end
end
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
83 changes: 51 additions & 32 deletions app/controllers/voter_controller.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# frozen_string_literal: true
require 'json'

class VoterController < ApplicationController
SKIP_WARN_THRESHOLDS = Set.new(Rails.configuration.rewards.skip_warnings)
Expand All @@ -14,7 +15,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 +42,63 @@ 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)
# 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'
redirect_to @voter
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

def update_survey
survey_data_from_form =
{
"issues" => {
"cares_climate" => params[:cares_about_climate].present? ? "1" : "0",
"cares_gun_control" => params[:cares_about_gun_control].present? ? "1" : "0",
"cares_healthcare" => params[:cares_about_healthcare].present? ? "1" : "0",
"cares_college_affordability" => params[:cares_about_college_affordability].present? ? "1" : "0",
"cares_reproductive_rights" => params[:cares_about_reproductive_rights].present? ? "1" : "0",
"cares_transparency" => params[:cares_about_transparency].present? ? "1" : "0",
"cares_marijuana" => params[:cares_about_marijuana].present? ? "1" : "0",
"cares_gender_equity" => params[:cares_about_gender_equity].present? ? "1" : "0",
"cares_pay_gap" => params[:cares_about_gender_pay_gap].present? ? "1" : "0",
"cares_sexual_assault" => params[:cares_about_sexual_assault].present? ? "1" : "0"
},
"plan_to_vote_before" => params[:planned_to_vote_before].present? ? "1" : "0",
"plan_to_vote_for_paul" => params[:planned_to_vote_for_paul].present? ? "1" : "0"
}

voter = Voter.find(params[:id])
if voter.update(survey_data: survey_data_from_form.to_json)
flash[:success] = 'Survey data updated'
else
flash[:danger] = 'Error updating survey responses, try again'
end

redirect_to voter
end

private

def voter_params
params.require(:voter).permit(:email, :last_call_status, :voter_registration_status, :notes, :party_id, :vote_plan, :vote_status)
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 +112,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(from: VOTER_FILE_LOCATION)
to_upsert = []

::CSV.foreach(from, 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"],
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.uniq { |v| v[:reach_id] }, unique_by: nil)
end

def load_users(from: USER_FILE_LOCATION)
to_upsert = []

::CSV.foreach(from, 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.uniq { |u| u[:id] }, unique_by: nil)
end

def load_relationships(from: RELATIONSHIP_FILE_LOCATION)
to_upsert = []
::CSV.foreach(from, 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.uniq { |r| "#{r[:user_id]} #{r[:voter_reach_id]}" }, 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
Loading