Skip to content

Commit

Permalink
Add option to order user project contributions by most recently contr…
Browse files Browse the repository at this point in the history
…ibuted (#76)

* update to include ordering project contributions by recents

* remove print statements

* adding specs

* fixing hound sniffs

* Update app/serializers/user_classification_counts_serializer.rb

Co-authored-by: Zach Wolfenbarger <[email protected]>

* Update app/serializers/user_classification_counts_serializer.rb

Co-authored-by: Zach Wolfenbarger <[email protected]>

---------

Co-authored-by: Zach Wolfenbarger <[email protected]>
  • Loading branch information
yuenmichelle1 and zwolf authored Oct 18, 2024
1 parent feff7d2 commit 52bb491
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 7 deletions.
15 changes: 13 additions & 2 deletions app/controllers/user_classification_count_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ class UserClassificationCountController < ApplicationController
before_action :sanitize_params
before_action :require_login

PROJ_CONTRIBUTIONS_ORDER_OPTIONS = {
recents: 'recents',
count: 'count'
}.freeze

def query
current_user['queried_user_id'] = params[:id]
authorize :queried_user_context, :show?
Expand All @@ -17,6 +22,11 @@ def query
def validate_params
super
raise ValidationError, 'Cannot query for project contributions and query by project/workflow' if params[:project_contributions] && (params[:workflow_id] || params[:project_id])
validate_order_proj_contributions if params[:order_project_contributions_by]
end

def validate_order_proj_contributions
raise ValidationError, 'Can only order project contributions by recents or count. Default behavior is count' unless PROJ_CONTRIBUTIONS_ORDER_OPTIONS.keys.include? params[:order_project_contributions_by].downcase.to_sym
end

def sanitize_params
Expand All @@ -27,10 +37,11 @@ def sanitize_params
def serializer_opts_from_params
{ period: params[:period],
time_spent: params[:time_spent],
project_contributions: params[:project_contributions] }
project_contributions: params[:project_contributions],
order_project_contributions_by: params[:order_project_contributions_by] }
end

def user_classification_count_params
params.permit(:id, :start_date, :end_date, :period, :workflow_id, :project_id, :project_contributions, :time_spent)
params.permit(:id, :start_date, :end_date, :period, :workflow_id, :project_id, :project_contributions, :time_spent, :order_project_contributions_by)
end
end
21 changes: 18 additions & 3 deletions app/serializers/user_classification_counts_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,22 @@ def as_json(options)
serializer_options = options[:serializer_options]
show_time_spent = serializer_options[:time_spent]
show_project_contributions = serializer_options[:project_contributions]
order_project_contributions_by = serializer_options[:order_project_contributions_by]

total_count = user_classification_counts.sum(&:count).to_i
response = { total_count: }
calculate_time_spent(user_classification_counts, response) if show_time_spent
response[:project_contributions] = project_contributions if show_project_contributions
response[:project_contributions] = project_contributions(order_project_contributions_by) if show_project_contributions
response[:data] = response_data(user_classification_counts, show_project_contributions:, show_time_spent:) if serializer_options[:period]
response
end

private

def order_project_contributions_by_recents?(order_project_contributions_by)
order_project_contributions_by && order_project_contributions_by.downcase == 'recents'
end

def calculate_time_spent(counts, response)
total_time_spent = counts.sum(&:session_time).to_f
response[:time_spent] = total_time_spent
Expand Down Expand Up @@ -48,10 +54,19 @@ def response_data(user_counts, show_project_contributions:, show_time_spent:)
end
end

def project_contributions
def project_contributions(order_by)
project_contributions = @user_classification_counts.group_by(&:project_id).transform_values do |counts|
counts.sum(&:count)
end
project_contributions.map { |project_id, count| { project_id:, count: } }.sort_by { |proj_contribution| proj_contribution[:count] }.reverse

if order_project_contributions_by_recents?(order_by)
period_to_contributed_project_ids = @user_classification_counts.sort_by(&:period).reverse.group_by(&:period).transform_values do |uccs|
uccs.map(&:project_id)
end
recently_contributed_project_ids = period_to_contributed_project_ids.values.flatten.uniq
recently_contributed_project_ids.map { |project_id| { project_id: , count: project_contributions[project_id] } }
else
project_contributions.map { |project_id, count| { project_id:, count: } }.sort_by { |proj_contribution| proj_contribution[:count] }.reverse
end
end
end
18 changes: 18 additions & 0 deletions spec/controllers/user_classification_count_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,24 @@
get :query, params: { id: 1, time_spent: 'true' }
expect(controller.params[:time_spent]).to eq(true)
end

context 'order_project_contributions validations' do
it 'errors if not a valid order_project_contributions_by option' do
get :query, params: { id: 1, order_project_contributions_by: 'blank' }
expect(response.status).to eq(400)
expect(response.body).to include('Can only order project contributions by recents or count')
end

it 'allows allowable order_project_contributions_by option' do
get :query, params: { id: 1, order_project_contributions_by: 'recents' }
expect(response.status).to eq(200)
end

it 'allows order_project_contributions_by to be case-insensitive' do
get :query, params: { id: 1, order_project_contributions_by: 'COUNT' }
expect(response.status).to eq(200)
end
end
end
end
end
26 changes: 24 additions & 2 deletions spec/serializers/user_classification_counts_serializer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
let(:user_diff_period_classification_count) { build(:user_diff_period_classification_count) }
let(:serializer) { described_class.new([user_diff_period_classification_count, user_classification_count, user_diff_proj_count]) }

it 'shows project_contributions ordered desc by count' do
it 'shows project_contributions ordered desc by count when order_proj_contribution_by by not given' do
serialized = serializer.as_json(serializer_options: { project_contributions: true })
expect(serialized[:project_contributions].length).to eq(2)
expect(serialized[:project_contributions][0][:project_id]).to eq(user_classification_count.project_id)
Expand All @@ -68,7 +68,29 @@
expect(serialized[:project_contributions][1][:count]).to eq(user_diff_proj_count.count)
end

it 'shows response data bucketed by period when querying top_projects' do
context 'when order_project_contributions_by param is given' do
it 'shows project_contributions ordered desc by count when order_proj_contribution_by is count' do
serialized = serializer.as_json(serializer_options: { project_contributions: true, order_project_contributions_by: 'count' })
expect(serialized[:project_contributions].length).to eq(2)
expect(serialized[:project_contributions][0][:project_id]).to eq(user_classification_count.project_id)
expect(serialized[:project_contributions][0][:count]).to eq(user_classification_count.count + user_diff_period_classification_count.count)
expect(serialized[:project_contributions][1][:project_id]).to eq(user_diff_proj_count.project_id)
expect(serialized[:project_contributions][1][:count]).to eq(user_diff_proj_count.count)
end

it 'shows project_contributions ordered by recents when order_proj_contribution_by is recents' do
classification_count_diff_project_created_yesterday = build(:user_diff_proj_classification_count, period: Date.today - 1)
serializer = described_class.new([classification_count_diff_project_created_yesterday, user_classification_count])
serialized = serializer.as_json(serializer_options: { project_contributions: true, order_project_contributions_by: 'recents' })
expect(serialized[:project_contributions].length).to eq(2)
expect(serialized[:project_contributions][0][:project_id]).to eq(user_classification_count.project_id)
expect(serialized[:project_contributions][0][:count]).to eq(user_classification_count.count)
expect(serialized[:project_contributions][1][:project_id]).to eq(classification_count_diff_project_created_yesterday.project_id)
expect(serialized[:project_contributions][1][:count]).to eq(classification_count_diff_project_created_yesterday.count)
end
end

it 'shows response data bucketed by period when querying project_contributions by count' do
serialized = serializer.as_json(serializer_options: { project_contributions: true, period: 'day' })
expect(serialized[:data].length).to eq(2)
expect(serialized[:data][0][:period]).to eq(user_diff_period_classification_count.period)
Expand Down

0 comments on commit 52bb491

Please sign in to comment.