Skip to content

Commit 1d624c0

Browse files
committed
for initial import of users from admin page
1 parent 8b0a26b commit 1d624c0

File tree

9 files changed

+150
-55
lines changed

9 files changed

+150
-55
lines changed

Rakefile

+4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ namespace :progbot do
1212
task :import_users do
1313
ImportUsersTask::Syncer.new.sync
1414
end
15+
desc "Update users from Admin Airtable Table"
16+
task :import_alternate_users do
17+
ImportUsersTask::Syncer.new.admin_sync
18+
end
1519
end
1620

1721
namespace :progbot do

app/admin/users.rb

+43-11
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,12 @@
66
#
77
# or
88
#
9-
# permit_params do
10-
# permitted = [:permitted, :attributes]
11-
# permitted << :other if params[:action] == 'create' && current_user.admin?
12-
# permitted
9+
# "welcome_email_sent", "attended_onboarding", "slack_invite_sent", "requested_additional_verification", "decline_membership", "irs_email_sent", "internal_notes", "contributor", "referrer_name", "skills_and_experience"
1310
# end
1411

1512
permit_params :referer_id, :name, :email, :join_reason, :overview, :location,
1613
:anonymous, :phone, :slack_username, :read_manifesto,
17-
:read_code_of_conduct, :optin, :hear_about_us, :verification_urls, :is_approved, :additional_info, :gender_pronouns, tech_skill_ids: [], non_tech_skill_ids: [], flags: []
14+
:read_code_of_conduct, :optin, :hear_about_us, :verification_urls, :is_approved, :additional_info, :welcome_email_sent, :attended_onboarding, :slack_invite_sent, :requested_additional_verification, :decline_membership, :irs_email_sent, :internal_notes, :contributor, :referrer_name, :skills_and_experience, :gender_pronouns, tech_skill_ids: [], non_tech_skill_ids: [], flags: []
1815

1916
action_item :bulk_import do
2017
link_to "Bulk Import From Airtable", admin_users_upload_csv_path
@@ -46,6 +43,13 @@
4643
filter :read_code_of_conduct, label: "Read Code of Conduct?"
4744
filter :optin, label: "Opted Into Skills Search?"
4845
filter :is_approved, label: "Approved?"
46+
filter :welcome_email_sent
47+
filter :attended_onboarding
48+
filter :slack_invite_sent
49+
filter :requested_additional_verification
50+
filter :decline_membership
51+
filter :irs_email_sent
52+
filter :contributor
4953
filter :referer, collection: User.where(id: User.pluck(:referer_id).compact.uniq)
5054
filter :gender_pronouns, as: :select, collection: UserConstants::GENDER_PRONOUNS, input_html: { multiple: true }
5155
filter :by_flagged_in, label: "Flagged?", as: :select, collection: %w[Yes No]
@@ -70,6 +74,8 @@
7074
row :join_reason
7175
row :overview
7276
row :hear_about_us
77+
row :referrer_name
78+
row :skills_and_experience
7379
row :verification_urls
7480
row :gender_pronouns
7581
row :additional_info
@@ -80,6 +86,14 @@
8086
row :read_manifesto
8187
row :read_code_of_conduct
8288
row :is_approved
89+
row :welcome_email_sent
90+
row :attended_onboarding
91+
row :slack_invite_sent
92+
row :requested_additional_verification
93+
row :decline_membership
94+
row :irs_email_sent
95+
row :contributor
96+
row :internal_notes
8397
row :flags do
8498
span user.flags.try(:join, "<br>").try(:html_safe)
8599
end
@@ -107,19 +121,26 @@ def upload_csv
107121
end
108122

109123
def import_data
124+
byebug
110125
@users = []
111126
@attributes = UserConstants::COLUMN_NAMES_FOR_DISPLAY
112127
CSV.foreach(params[:file].path, headers: true) do |row|
128+
table_type = params["airtable_type"]
129+
airtable_id = row["Record ID"]
113130
if row[0].present?
114-
airtable_id = row["Record ID"]
115-
airtable_user = AirtableUser.find(airtable_id)
116-
if User.where(airtable_id: airtable_id).present?
117-
user = User.find_by(airtable_id: airtable_id)
118-
else
131+
132+
if table_type == "admin"
133+
airtable_user = AirtableUserFromAdmin.find(airtable_id)
119134
user = User.find_or_initialize_by(email: airtable_user["Contact E-Mail"])
135+
elsif table_type == "prog_apps"
136+
airtable_user = AirtableUser.find(airtable_id)
137+
user = User.where(airtable_id: airtable_id).first
138+
if user.blank?
139+
user = User.find_or_initialize_by(email: airtable_user["Contact E-Mail"])
140+
end
120141
user.airtable_id = airtable_id
121142
end
122-
user.sync_with_airtable(airtable_user)
143+
user.sync_with_airtable(airtable_user, table_type)
123144
@users << user
124145
end
125146
end
@@ -136,6 +157,7 @@ def import_data
136157
f.input :slack_username
137158
f.input :location
138159
f.input :phone
160+
f.input :referrer_name
139161
f.input :referer
140162
f.input :gender_pronouns, as: :select, collection: UserConstants::GENDER_PRONOUNS
141163
end
@@ -144,6 +166,7 @@ def import_data
144166
f.input :join_reason
145167
f.input :overview
146168
f.input :hear_about_us
169+
f.input :skills_and_experience
147170
f.input :additional_info
148171
end
149172

@@ -166,6 +189,15 @@ def import_data
166189
f.inputs "Admin Approval" do
167190
f.input :is_approved, label: "Is This An Approved Progcode Member?"
168191
f.input :verification_urls
192+
f.input :welcome_email_sent
193+
f.input :attended_onboarding
194+
f.input :slack_invite_sent
195+
f.input :requested_additional_verification
196+
f.input :decline_membership
197+
f.input :irs_email_sent
198+
f.input :contributor
199+
f.input :internal_notes
200+
169201
end
170202

171203
f.actions

app/assets/stylesheets/active_admin.scss

+4
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,7 @@
1616
// For example, to change the default status-tag color:
1717
//
1818
// .status_tag { background: #6090DB; }
19+
20+
.row {
21+
margin:25px;
22+
}
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Airrecord.api_key = ENV['AIRTABLE_API_KEY']
2+
3+
4+
class AirtableUserFromAdmin < Airrecord::Table
5+
self.base_key = ENV['AIRTABLE_ADMIN_BASE_KEY']
6+
self.table_name = ENV['AIRTABLE_ADMIN_TABLE_NAME']
7+
8+
end

app/models/user.rb

+67-31
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ class User < ApplicationRecord
2020
has_many :active_volunteerings, -> { where state: 'active' }, class_name: 'Volunteering'
2121
has_many :projects, through: :active_volunteerings, source: 'user'
2222

23-
before_save :push_changes_to_airtable, unless: :skip_push_to_airtable
23+
# before_save :push_changes_to_airtable, unless: :skip_push_to_airtable
2424

25-
after_create :send_slack_notification, unless: :skip_slack_notification
25+
# after_create :send_slack_notification, unless: :skip_slack_notification
2626

2727
devise :omniauthable, omniauth_providers: [:slack]
2828

@@ -180,7 +180,7 @@ def airtable_twin
180180
end
181181
end
182182

183-
def sync_with_airtable(airtable_user)
183+
def sync_with_airtable(airtable_user, airtable_table)
184184
self.skip_push_to_airtable = true
185185

186186
if self.new_record?
@@ -199,41 +199,77 @@ def sync_with_airtable(airtable_user)
199199
self.non_tech_skill_ids = Skill.match_with_airtable(airtable_skills: airtable_user["Non-Tech Skills and Specialties"], tech: false)
200200
end
201201

202-
self.assign_attributes({
203-
name: airtable_user["Name"],
204-
email: airtable_user["Contact E-Mail"],
205-
slack_username: airtable_user["Member Handle"],
206-
slack_userid: airtable_user["slack_id"],
207-
optin: airtable_user["Optin"],
208-
join_reason: airtable_user["Join Reason"],
209-
overview: airtable_user["Overview"],
210-
location: airtable_user["Location"],
211-
phone: airtable_user["Phone"],
212-
hear_about_us: airtable_user["Hear About Us"],
213-
verification_urls: airtable_user["Verification URLs"],
214-
gender_pronouns: airtable_user["Gender Pronouns"],
215-
additional_info: airtable_user["Additional Info"],
216-
anonymous: airtable_user["Anonymous"],
217-
read_manifesto: airtable_user["Read Manifesto"],
218-
read_code_of_conduct: airtable_user["Read Code of Conduct"]
219-
})
202+
if airtable_table == "prog apps"
203+
204+
self.assign_attributes({
205+
name: airtable_user["Name"],
206+
email: airtable_user["Contact E-Mail"],
207+
slack_username: airtable_user["Member Handle"],
208+
slack_userid: airtable_user["slack_id"],
209+
optin: airtable_user["Optin"],
210+
join_reason: airtable_user["Join Reason"],
211+
overview: airtable_user["Overview"],
212+
location: airtable_user["Location"],
213+
phone: airtable_user["Phone"],
214+
hear_about_us: airtable_user["Hear About Us"],
215+
verification_urls: airtable_user["Verification URLs"],
216+
gender_pronouns: airtable_user["Gender Pronouns"],
217+
additional_info: airtable_user["Additional Info"],
218+
anonymous: airtable_user["Anonymous"],
219+
read_manifesto: airtable_user["Read Manifesto"],
220+
read_code_of_conduct: airtable_user["Read Code of Conduct"]
221+
})
220222

221-
self.is_approved = true
223+
self.is_approved = true
222224

223-
if self.email.blank?
224-
if self.has_slack?
225-
self.get_email_from_slack
225+
if self.email.blank?
226+
if self.has_slack?
227+
self.get_email_from_slack
228+
end
229+
end
230+
231+
if self.slack_userid.blank? && self.slack_username.present?
232+
self.get_slack_userid
233+
elsif self.slack_userid.present? && self.slack_username.blank?
234+
self.get_slack_username
235+
end
236+
237+
elsif airtable_table == "admin"
238+
self.assign_attributes({
239+
name: airtable_user["Name"],
240+
read_code_of_conduct: airtable_user["Read Code of Conduct"],
241+
anonymous: airtable_user["I prefer to remain anonymous."],
242+
welcome_email_sent: airtable_user["Welcome E-mail Sent"],
243+
attended_onboarding: airtable_user["Attended Onboarding"],
244+
slack_invite_sent: airtable_user["Slack invite sent?"],
245+
requested_additional_verification: airtable_user["Requested additional verification"],
246+
decline_membership: airtable_user["Declime Membership"],
247+
irs_email_sent: airtable_user["IRS Email Sent"],
248+
internal_notes: airtable_user["Internal Notes"],
249+
contributor: airtable_user["Contributor?"],
250+
email: airtable_user["Contact E-Mail"],
251+
verification_urls: airtable_user["Verification URLs"],
252+
hear_about_us: airtable_user["How did you hear about us?"],
253+
referrer_name: airtable_user["Name of ProgCode member who referred you."],
254+
skills_and_experience: airtable_user["Skills and Relevant Experience (Tech or Non-Tech)"],
255+
join_reason: airtable_user["Bio"],
256+
phone: airtable_user["Phone"],
257+
optin: airtable_user["Opt In to Anonymized Member Directory"],
258+
location: airtable_user["Location"],
259+
read_manifesto: airtable_user["Read Manifesto"]
260+
})
261+
262+
if self.decline_membership
263+
self.is_approved = false
264+
elsif self.welcome_email_sent
265+
self.is_approved = true
226266
end
227-
end
228267

229-
if self.slack_userid.blank? && self.slack_username.present?
230-
self.get_slack_userid
231-
elsif self.slack_userid.present? && self.slack_username.blank?
232-
self.get_slack_username
233268
end
234269

235270
if self.email.present? || self.slack_userid.present?
236-
matches = AirtableUser.all.select {|u| (self.email.present? && u["Contact E-Mail"] == self.email) || (self.slack_userid.present? && u["slack_id"] == self.slack_userid)}
271+
all_airtable_users = airtable_table == 'admin' ? AirtableUserFromAdmin.all : AirtableUser.all
272+
matches = all_airtable_users.select {|u| (self.email.present? && u["Contact E-Mail"] == self.email) || (self.slack_userid.present? && u["slack_id"] == self.slack_userid)}
237273
if matches.length > 1
238274
self.flags << "This user appears more than once in Airtable"
239275
end
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
<h1>Import <%= controller_name.singularize.titleize %> Data from Airtable</h1>
22
<%= form_tag({:controller => controller_path, :action => 'import_data'}, multipart: true) do %>
3-
<%= file_field_tag :file, :class => "btn" %>
4-
<%= hidden_field_tag :confirmation, "pending" %>
5-
<%= submit_tag "Import", :class => "btn", :disabled => true %>
3+
<div class="row"><%= file_field_tag :file, :class => "btn" %></div>
4+
<div class="row"><%= label_tag 'airtable_type_prog_apps', 'From Prog Apps Table' %>
5+
<%= radio_button_tag 'airtable_type', 'prog_apps', true %>
6+
</div>
7+
<div class="row">
8+
<%= label_tag 'airtable_type_admin', 'From Admin Table' %>
9+
<%= radio_button_tag 'airtable_type', 'admin' %></div>
10+
<div class="row"><%= hidden_field_tag :confirmation, "pending" %>
11+
<%= submit_tag "Import", :class => "btn", :disabled => true %></div>
612
<% end %>

db/migrate/20210219040742_add_fields_to_users.rb

+1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ def change
99
add_column :users, :internal_notes, :text
1010
add_column :users, :contributor, :boolean
1111
add_column :users, :referrer_name, :string
12+
add_column :users, :skills_and_experience, :text
1213
end
1314
end

db/schema.rb

+1
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@
174174
t.text "internal_notes"
175175
t.boolean "contributor"
176176
t.string "referrer_name"
177+
t.text "skills_and_experience"
177178
t.index ["airtable_id"], name: "index_users_on_airtable_id", unique: true
178179
t.index ["email"], name: "index_users_on_email", unique: true
179180
t.index ["referer_id"], name: "index_users_on_referer_id"

lib/tasks/import_users_task.rb

+13-10
Original file line numberDiff line numberDiff line change
@@ -32,19 +32,22 @@ def sync
3232
end
3333
end
3434

35-
user.sync_with_airtable(airtable_user)
35+
user.sync_with_airtable(airtable_user, 'prog apps')
3636
end
3737
end
38-
39-
def sync_slack_ids_for_users
40-
SlackBot.client
41-
User.all.each do |u|
42-
next if u.email.blank? || u.slack_userid.present?
43-
slack_user = SlackHelpers.lookup_by_email(u.email.downcase)
44-
next if slack_user.blank?
45-
u.slack_userid = slack_user.id
46-
u.save(:validate => false)
38+
39+
def admin_sync
40+
AirtableUserFromAdmin.all.each do |airtable_user|
41+
if airtable_user["Contact E-Mail"].blank?
42+
puts "Email not in record: #{airtable_user.inspect}"
43+
next
44+
else
45+
user = User.find_or_initialize_by email: airtable_user["Contact E-Mail"]
46+
47+
user.sync_with_airtable(airtable_user, 'admin')
48+
end
4749
end
4850
end
51+
4952
end
5053
end

0 commit comments

Comments
 (0)