Skip to content
Merged
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
42 changes: 41 additions & 1 deletion app/controllers/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ class UsersController < ApplicationController
)
before_action(
:authenticate_officer!,
only: %i[community_member_grant community_member_deny]
only: %i[
community_member_grant community_member_deny community_members_active
]
)
before_action(
:set_user,
Expand Down Expand Up @@ -190,8 +192,46 @@ def community_member_deny
)
end

# GET /community_members/active
# GET /community_members/active.csv
def community_members_active
members = User.community_members_active.order(:family, :given)
respond_to do |format|
format.html do
@crumbs = [
['Officer dashboard', dashboard_path(tab: :officer)],
'Active community members'
]
@members = members.paginate(page: params[:page], per_page: 30)
end
format.csv do
send_data(
community_members_csv(members), type: 'text/csv',
filename: "seqcode-community-members-#{Date.current}.csv"
)
end
end
end

private

def community_members_csv(members)
CSV.generate do |rows|
rows << ['Full name', 'Email', 'Affiliation', 'Department', 'Position']
members.each do |u|
rows << [
u.full_name, u.email, u.affiliation, u.department, u.position
].map { |value| csv_safe(value) }
end
end
end

# Prevent spreadsheet applications from interpreting user-provided
# +value+ as a formula
def csv_safe(value)
value.to_s.start_with?('=', '+', '-', '@') ? "'#{value}" : value
end

# Update the +@user+ status with +params+, and record +membership_event+
# if it's a SeqCode Community membership change
def status_application_action(params, membership_event: nil)
Expand Down
12 changes: 12 additions & 0 deletions app/views/users/_officer.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,17 @@
(<%= @active_community_members.count %>)
<% end %>
</li>
<li class="nav-item">
<%= link_to(community_members_active_path) do %>
<%= fa_icon('list') %>
List all active community members
<% end %>
</li>
<li class="nav-item">
<%= link_to(community_members_active_path(format: :csv)) do %>
<%= fa_icon('file-csv') %>
Download active community members (CSV)
<% end %>
</li>
</ul>
<% end %>
27 changes: 27 additions & 0 deletions app/views/users/community_members_active.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<%= download_buttons(
[[community_members_active_url(format: :csv), 'file-csv', 'CSV']]
) %>

<h1>
Active community members
<div class="badge badge-count"><%= @members.total_entries %></div>
</h1>
<div class="container p-0">
<div class="row">
<div class="col-sm-12 text-right">
<%= list_type_selector %>
</div>
</div>
</div>
<hr/>

<%= adaptable_list(set: @members) do |list| %>
<% @members.each do |member| %>
<%= adaptable_entry(list, member.full_name, "mailto:#{member.email}") do |entry| %>
<%= adaptable_value(entry, 'Email') { member.email } %>
<%= adaptable_value(entry, 'Affiliation') { member.affiliation } %>
<%= adaptable_value(entry, 'Department') { member.department } %>
<%= adaptable_value(entry, 'Position') { member.position } %>
<% end %>
<% end %>
<% end %>
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
post 'community_members/apply' => 'users#community_member_apply', as: :community_member_apply
post 'community_members/grant/:username' => 'users#community_member_grant', as: :community_member_grant
post 'community_members/deny/:username' => 'users#community_member_deny', as: :community_member_deny
get 'community_members/active(.:format)' => 'users#community_members_active', as: :community_members_active
devise_for(:users, controllers: { registrations: 'users/registrations' })

namespace :wikispecies do
Expand Down
77 changes: 77 additions & 0 deletions test/controllers/users_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,83 @@ class UsersControllerTest < ActionDispatch::IntegrationTest
assert_match('mailto:seqcode@bio.aau.dk', response.body)
end

test 'community_members_active downloads active members as CSV' do
sign_in(@officer)
@contributor.update!(
given: 'Ada', family: 'Lovelace', affiliation: '=HYPERLINK("x")',
department: 'Computing', position: 'Graduate Student',
community_member: true, community_member_expires_on: Date.current
)
@admin.update!(
community_member: true,
community_member_expires_on: Date.current - 1.day
)

get(community_members_active_path(format: :csv))

assert_response(:success)
assert_equal('text/csv', response.media_type)
assert_match(
"seqcode-community-members-#{Date.current}.csv",
response.headers['Content-Disposition']
)
assert_equal(
[
['Full name', 'Email', 'Affiliation', 'Department', 'Position'],
[
'Lovelace, Ada', 'contributor@example.com', %q('=HYPERLINK("x")),
'Computing', 'Graduate Student'
]
],
CSV.parse(response.body)
)
end

test 'community_members_active lists active members in HTML' do
sign_in(@officer)
@contributor.update!(
given: 'Ada', family: 'Lovelace', affiliation: 'Analytical Engines',
community_member: true, community_member_expires_on: Date.current
)
@admin.update!(
community_member: true,
community_member_expires_on: Date.current - 1.day
)

get(community_members_active_path)

assert_response(:success)
assert_select('h1 .badge-count', text: '1')
assert_select('a[href=?]', 'mailto:contributor@example.com',
text: 'Lovelace, Ada')
assert_select('a[href=?]', 'mailto:admin@example.com', count: 0)
assert_match('Analytical Engines', response.body)
assert_select(
'a.btn[href=?]', community_members_active_url(format: :csv), text: 'CSV'
)
end

test 'community_members_active is not accessible to non-officers' do
sign_in(@admin)

get(community_members_active_path)
assert_redirected_to(root_path)

get(community_members_active_path(format: :csv))
assert_redirected_to(root_path)
end

test 'officer dashboard tab links to the active members list and CSV' do
sign_in(@officer)

get(dashboard_path(tab: :officer))

assert_select('a[href=?]', community_members_active_path)
assert_select(
'a[href=?]', community_members_active_path(format: :csv)
)
end

test 'officer dashboard tab renders with no pending applications or members' do
sign_in(@officer)

Expand Down
Loading