Skip to content

Commit

Permalink
Merge branch 'dev' into 88_evaluators_evaluation_progress_summary
Browse files Browse the repository at this point in the history
  • Loading branch information
emmabjj authored Jan 8, 2025
2 parents 591872b + 00a8652 commit 3c60b80
Show file tree
Hide file tree
Showing 14 changed files with 705 additions and 388 deletions.
99 changes: 29 additions & 70 deletions app/controllers/phases_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,25 @@ def index
end

def submissions
@submissions = @phase.submissions
@submissions = @phase.submissions.includes(evaluator_submission_assignments: [:evaluator, :evaluation])

set_submission_counts
set_submission_statuses

apply_filters
apply_sorting
@submissions = SubmissionsSortAndFilterService.new(
@submissions,
params,
{
not_started: @not_started,
in_progress: @in_progress,
completed: @completed
}
).sort_and_filter

@filtered_count = @submissions.unscope(:group).distinct.count(:id)
@submissions = paginate_submissions(@submissions)

respond_to do |format|
format.html do
if params[:partial]
render partial: 'submissions_table_rows',
locals: { submissions: @submissions },
formats: [:html]
else
render :submissions
end
end
end
render_response
end

private
Expand All @@ -41,6 +38,10 @@ def set_phase
@challenge = @phase.challenge
end

def evaluator_assignments?
EvaluatorSubmissionAssignment.exists?(submission_id: @submissions.select(:id))
end

def set_submission_counts
@submissions_count = @submissions.count
@eligible_count = @submissions.eligible_for_evaluation.count
Expand All @@ -62,65 +63,23 @@ def set_submission_statuses
}
end

def apply_filters
filter_by_eligibility
filter_by_status
end

def filter_by_eligibility
return unless params[:eligible_for_evaluation] == 'true' ||
params[:selected_to_advance] == 'true'

@submissions = apply_eligibility_filter(@submissions)
end

def filter_by_status
return unless params[:status]

@submissions = apply_status_filter(@submissions)
end

def apply_status_filter(submissions)
case params[:status]
when 'not_started' then @not_started
when 'in_progress' then @in_progress
when 'completed' then @completed
when 'recused' then filter_recused_submissions
else submissions
end
end

def filter_recused_submissions
@submissions.joins(:evaluator_submission_assignments).
where(evaluator_submission_assignments: { status: :recused })
end

def apply_eligibility_filter(submissions)
if params[:selected_to_advance] == 'true'
submissions.where(judging_status: %w[winner])
elsif params[:eligible_for_evaluation] == 'true'
submissions.where(judging_status: %w[selected winner])
else
submissions
end
end

def apply_sorting
case params[:sort]
when 'average_score_high_to_low'
@submissions = @submissions.order_by_average_score(:desc)
when 'average_score_low_to_high'
@submissions = @submissions.order_by_average_score(:asc)
when 'submission_id_high_to_low'
@submissions = @submissions.order(id: :desc)
when 'submission_id_low_to_high'
@submissions = @submissions.order(id: :asc)
end
end

def paginate_submissions(submissions)
page = (params[:page] || 1).to_i
per_page = 20
submissions.offset((page - 1) * per_page).limit(per_page)
end

def render_response
respond_to do |format|
format.html do
if params[:partial]
render partial: 'submissions_table_rows',
locals: { submissions: @submissions },
formats: [:html]
else
render :submissions
end
end
end
end
end
24 changes: 19 additions & 5 deletions app/controllers/submissions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ class SubmissionsController < ApplicationController
def show; end

def update
if @submission.update!(submission_params)
flash.now[:success] = I18n.t("submission_updated")
render :show, submission: @submission
else
render :show, status: :unprocessable_entity, submission: @submission
respond_to do |format|
if @submission.update(submission_params)
handle_successful_update(format)
else
handle_failed_update(format)
end
end
end

Expand All @@ -26,4 +27,17 @@ def submission_params
def set_submission
@submission = Submission.by_user(current_user).find(params[:id])
end

def handle_successful_update(format)
format.html do
flash[:success] = I18n.t("submission_updated")
redirect_to submission_path(@submission)
end
format.json { render json: { submission: @submission } }
end

def handle_failed_update(format)
format.html { render :show }
format.json { render json: { errors: @submission.errors }, status: :unprocessable_entity }
end
end
7 changes: 2 additions & 5 deletions app/helpers/evaluations_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,8 @@ def display_score(assignment)

# individual evaluator score
def evaluator_score(assignment)
score = assignment.evaluation&.total_score

unless assignment.evaluation_status == :completed && score
return Score.new(0, "0", "N/A")
end
score = display_score(assignment)
return Score.new(0, "0", "N/A") if score == 'N/A'

Score.new(score, score.to_s, score)
end
Expand Down
7 changes: 5 additions & 2 deletions app/javascript/controllers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@ application.register("evaluation-form", EvaluationFormController);
import HotdogController from "./hotdog_controller";
application.register("hotdog", HotdogController);

import LoadMoreController from "./load_more_controller";
application.register("load-more", LoadMoreController);

import SubmissionDetailsController from "./submission_details_controller";
application.register("submission-details", SubmissionDetailsController);

import LoadMoreController from "./load_more_controller";
application.register("load-more", LoadMoreController);
import SubmissionJudgingStatusController from "./submission_judging_status_controller";
application.register("submission-judging-status", SubmissionJudgingStatusController);

import ModalController from "./modal_controller";
application.register("modal", ModalController);
Expand Down
45 changes: 45 additions & 0 deletions app/javascript/controllers/submission_judging_status_controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// app/javascript/controllers/submission_judging_status_controller.js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
static targets = ["eligibilityForm", "advancementForm", "eligibilityCheckbox", "advancementCheckbox"]

toggleEligibility(event) {
event.preventDefault()
const formData = new FormData(this.eligibilityFormTarget)
formData.set('submission[judging_status]',
event.target.checked ? 'selected' : 'not_selected'
)
this.submitForm(formData, this.eligibilityFormTarget)
}

toggleAdvancement(event) {
event.preventDefault()
const formData = new FormData(this.advancementFormTarget)
formData.set('submission[judging_status]',
event.target.checked ? 'winner' : 'selected'
)

if (event.target.checked) {
this.eligibilityCheckboxTarget.checked = true
}
this.submitForm(formData, this.advancementFormTarget)
}

submitForm(formData, form) {
const csrfToken = document.querySelector('[name="csrf-token"]').content

fetch(form.action, {
method: 'PATCH',
headers: {
'X-CSRF-Token': csrfToken,
'Accept': 'application/json'
},
body: formData
})
.catch(() => {
const checkbox = form.querySelector('input[type="checkbox"]')
checkbox.checked = !checkbox.checked
})
}
}
7 changes: 5 additions & 2 deletions app/models/evaluator_submission_assignment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,12 @@ def self.ordered_by_status
end

def evaluation_status
return status.to_sym unless assigned?
return :recused if recused?
return :unassigned if unassigned?
return :recused_unassigned if recused_unassigned?
return assigned_evaluation_status if assigned?

assigned_evaluation_status
status&.to_sym
end

private
Expand Down
63 changes: 49 additions & 14 deletions app/models/submission.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ class Submission < ApplicationRecord

# Validations
validates :title, presence: true
validate :can_be_selected_to_advance,
if: -> { judging_status_change == %w[selected winner] }
validate :can_be_ineligible_for_evaluation,
if: -> { judging_status_change == %w[selected not_selected] }

scope :by_user, lambda { |user|
case user.role
Expand All @@ -63,20 +67,7 @@ class Submission < ApplicationRecord
}
scope :eligible_for_evaluation, -> { where(judging_status: [:selected, :winner]) }

def eligible_for_evaluation?
selected? or winner?
end

def selected_to_advance?
winner?
end

def average_score
avg = evaluations.average(:total_score)
avg ? avg.round : 0
end

def self.order_by_average_score(direction)
scope :order_by_average_score, lambda { |direction|
direction_sql = direction == :desc ? 'DESC' : 'ASC'

joins(
Expand All @@ -90,5 +81,49 @@ def self.order_by_average_score(direction)
"submissions.id #{direction_sql}"
)
)
}

def eligible_for_evaluation?
selected? or winner?
end

def average_score
avg = evaluations.joins(:evaluator_submission_assignment).
where(evaluator_submission_assignments: { status: :assigned }).
where.not(completed_at: nil).
average(:total_score)

avg ? avg.round : 0
end

def selected_to_advance?
winner?
end

def evaluators_assigned?
evaluator_submission_assignments.exists?(status: [:assigned, :recused])
end

def evaluations_missing_or_incomplete?
!eligible_for_evaluation? || !all_evaluations_completed? || evaluator_submission_assignments.empty?
end

private

def all_evaluations_completed?
evaluator_submission_assignments.
all? { |assignment| assignment.evaluation_status == :completed }
end

def can_be_selected_to_advance
return unless evaluations_missing_or_incomplete?

errors.add(:judging_status, "can't be selected to advance until all evaluations are complete")
end

def can_be_ineligible_for_evaluation
return unless evaluators_assigned?

errors.add(:judging_status, "must remain eligible for evaluation when evaluators are assigned")
end
end
Loading

0 comments on commit 3c60b80

Please sign in to comment.