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

Add option to order user project contributions by most recently contributed #76

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
yuenmichelle1 marked this conversation as resolved.
Show resolved Hide resolved
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] } }
yuenmichelle1 marked this conversation as resolved.
Show resolved Hide resolved
else
project_contributions.map { |project_id, count| { project_id:, count: } }.sort_by { |proj_contribution| proj_contribution[:count] }.reverse
yuenmichelle1 marked this conversation as resolved.
Show resolved Hide resolved
end
yuenmichelle1 marked this conversation as resolved.
Show resolved Hide resolved
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
Loading