Skip to content

Commit

Permalink
Merge pull request #329 from GSA/75_evaluator_submission_assignment
Browse files Browse the repository at this point in the history
[75] Assign Evaluators to a Submission
  • Loading branch information
stonefilipczak authored Jan 8, 2025
2 parents 00a8652 + 3b2042e commit 5baef9a
Show file tree
Hide file tree
Showing 14 changed files with 320 additions and 75 deletions.
30 changes: 26 additions & 4 deletions app/controllers/evaluator_submission_assignments_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
class EvaluatorSubmissionAssignmentsController < ApplicationController
before_action -> { authorize_user('challenge_manager') }
before_action :set_challenge_and_phase
before_action :set_evaluator, only: [:index]
before_action :set_evaluator, only: [:index, :create]
before_action :set_assignment, only: [:update]
before_action :set_submission, only: [:create]

def index
@evaluator_assignments = @phase.evaluator_submission_assignments.includes(:submission).where(user_id: @evaluator.id)
Expand All @@ -19,6 +20,19 @@ def index
@submissions_count = calculate_submissions_count(@assigned_submissions)
end

def create
@evaluator_submission_assignment = EvaluatorSubmissionAssignment.new(
user_id: params["evaluator_id"],
submission_id: @submission.id,
status: :assigned
)
if @evaluator_submission_assignment.save
redirect_to submission_path(@submission), notice: I18n.t("evaluator_submission_assignments.assigned.success")
else
redirect_to submission_path(@submission), notice: I18n.t("evaluator_submission_assignments.assigned.failure")
end
end

# update only the status of the evaluation submission assignment to unassign or reassign an evaluator
def update
new_status = status_from_params
Expand Down Expand Up @@ -49,6 +63,10 @@ def set_assignment
@assignment = @phase.evaluator_submission_assignments.find(params[:id])
end

def set_submission
@submission = @phase.submissions.find(params[:submission_id])
end

def status_from_params
status = params[:status] || params.dig(:evaluator_submission_assignment, :status)
status&.to_sym
Expand All @@ -68,9 +86,13 @@ def update_assignment_status(new_status)

def handle_successful_update(new_status)
flash[:success] = t("evaluator_submission_assignments.#{new_status}.success")
respond_to do |format|
format.html { redirect_to_assignment_path }
format.json { render json: { success: true, message: flash[:success] } }
if request&.referer&.include?("submissions")
redirect_to request.referer
else
respond_to do |format|
format.html { redirect_to_assignment_path }
format.json { render json: { success: true, message: flash[:success] } }
end
end
end

Expand Down
6 changes: 6 additions & 0 deletions app/models/submission.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ class Submission < ApplicationRecord
)
}

# Phase evaluators not currently assigned or recused on the submission
def available_evaluators
unavailable_evaluators = evaluators.where.not("evaluator_submission_assignments.status" => "unassigned")
phase.evaluators.where.not(id: unavailable_evaluators)
end

def eligible_for_evaluation?
selected? or winner?
end
Expand Down
2 changes: 1 addition & 1 deletion app/views/shared/_alert_error.html.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div class="grid-row margin-top-105">
<div class="grid-col-12 tablet:grid-col-6">
<div class="maxw-mobile-lg">
<div class="usa-alert usa-alert--error padding-top-105" role="alert">
<div class="usa-alert__body">
<h2 class="usa-alert__heading"><%= alert_heading %></h2>
Expand Down
58 changes: 58 additions & 0 deletions app/views/submissions/_assigned_evaluators.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<div class="usa-accordion">
<% rand = SecureRandom.hex(8) %>
<h2 class="usa-accordion__heading" id="<%= "#{rand}-accordion-heading" %>">
<button
type="button"
class="usa-accordion__button display-flex flex-justify icon-white"
aria-expanded="true"
aria-controls="<%= rand %>"
>
<div>Assigned Evaluators</div>
</button>
</h2>

<div class="usa-accordion__content" id="<%= rand %>">
<% assigned_evaluators = @submission.evaluators.where("evaluator_submission_assignments.status" => ["assigned", "recused"]) %>
<% if assigned_evaluators.any? %>
<table class="usa-table usa-table--stacked-header usa-table--borderless gray-header">
<thead>
<tr>
<th scope="col">Evaluator name</th>
<th scope="col">Evaluation Status</th>
<th scope="col">Score</th>
<th scope="col" aria-label="Actions"></th>
</tr>
</thead>
<tbody>
<% assigned_evaluators.each do |evaluator| %>
<tr data-evaluator-id="<%= evaluator.id %>" data-evaluator-type="user">
<th scope="row" data-label="Evaluator name" class="text-top">
<span class="text-bold text-ls-1 line-height-sans-4"><%= "#{evaluator.first_name} #{evaluator.last_name}" %></span>
</th>
<td data-label="Evaluation Status" class="text-top"></td>
<td data-label="Score" class="text-top"></td>
<td data-label="">
<div class="display-flex flex-no-wrap grid-row">
<% assignment = evaluator.evaluator_submission_assignments.where(submission_id: @submission.id).first %>
<%= form_with url: phase_evaluator_submission_assignment_path(@submission.phase, assignment.id), method: "PATCH" do |f| %>
<%= f.hidden_field :phase_id, value: @submission.phase.id %>
<%= f.hidden_field :status, value: assignment.recused? ? "recused_unassigned" : "unassigned" %>
<%= f.submit "Unassign", class: "usa-button usa-button--outline font-body-2xs" %>
<% end %>
</div>
</td>
</tr>
<% end %>
</tbody>
</table>
<% else %>
<div class="usa-alert usa-alert--warning">
<div class="usa-alert__body">
<p class="usa-alert__text font-body-2xs">
You currently do not have any evaluators assigned to this submission. Please use the section below to review and assign available evaluators.
</p>
</div>
</div>
<% end %>
</div>
</div>
53 changes: 53 additions & 0 deletions app/views/submissions/_available_evaluators.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<div class="usa-accordion">
<% rand = SecureRandom.hex(8) %>
<h2 class="usa-accordion__heading" id="<%= "#{rand}-accordion-heading" %>">
<button
type="button"
class="usa-accordion__button display-flex flex-justify icon-white"
aria-expanded="true"
aria-controls="<%= rand %>"
>
<div>Available Evaluators</div>
</button>
</h2>

<div class="usa-accordion__content bg-base-lighter width-full" id="<%= rand %>">
<% if @submission.available_evaluators.any? %>
<% @submission.available_evaluators.each_with_index do |evaluator, i| %>
<div class="display-flex flex-justify margin-y-1">
<div style="word-break: break-all">
<span class="text-bold"><%= "#{evaluator.first_name} #{evaluator.last_name}" %></span><br/>
<%= evaluator.email %>
</div>
<div class="margin-left-05">
<% assignment = evaluator.evaluator_submission_assignments.where(submission_id: @submission.id).first %>
<% if assignment %>
<%= form_with url: phase_evaluator_submission_assignment_path(@submission.phase, assignment.id), method: "PATCH" do |f| %>
<%= f.hidden_field :phase_id, value: @submission.phase.id %>
<%= f.hidden_field :status, value: "assigned" %>
<%= f.submit "Reassign", class: "usa-button font-body-2xs margin-top-1" %>
<% end %>
<% else %>
<%= form_with url: phase_evaluator_submission_assignments_path(@submission.phase) do |f| %>
<%= f.hidden_field :evaluator_id, value: evaluator.id %>
<%= f.hidden_field :submission_id, value: @submission.id %>
<%= f.submit "Assign", class: "usa-button font-body-2xs margin-top-1" %>
<% end %>
<% end %>
</div>
</div>
<% if i < @submission.available_evaluators.length - 1 %>
<hr/>
<% end %>
<% end %>
<% else %>
<div class="usa-alert usa-alert--warning">
<div class="usa-alert__body">
<p class="usa-alert__text font-body-2xs">
There are no evaluators available for this submission. Please visit Evaluation Panel section to manage your list of available evaluators.
</p>
</div>
</div>
<% end %>
</div>
</div>
53 changes: 53 additions & 0 deletions app/views/submissions/_details_form.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<div data-controller="submission-details">
<% rand = SecureRandom.hex(8) %>
<%= form_with(model: @submission, url: submission_path(@submission), class: "maxw-mobile-lg") do |form| %>
<div class="usa-checkbox" id="eligible-for-evaluation">
<input
class="usa-checkbox__input usa-checkbox__input--tile"
type="checkbox"
id="<%= "#{rand}-judging-status-selected" %>"
value="selected"
<%= "disabled" if @submission.evaluators_assigned? %>
<%= "checked" if @submission.judging_status.in?(["selected", "winner"]) %>
data-action="change->submission-details#eligibleCheck"
data-submission-details-target="eligibleCheckbox"
/>
<label class="usa-checkbox__label" for="<%= "#{rand}-judging-status-selected" %>"
>This submission is eligible for evaluation.
<span class="usa-checkbox__label-description"
>Check the box if the submission is pre-screened and is eligible for the evaluation process.</span
></label
>
</div>
<div class="usa-checkbox" id="selected-to-advance">
<input
class="usa-checkbox__input usa-checkbox__input--tile"
id="<%= "#{rand}-judging-status-winner" %>"
type="checkbox"
<%= "disabled" if @submission.evaluations_missing_or_incomplete? %>
<%= "checked" if @submission.judging_status == "winner" %>
data-action="change->submission-details#selectedCheck"
data-submission-details-target="winnerCheckbox"
/>
<label class="usa-checkbox__label" for="<%= "#{rand}-judging-status-winner" %>"
>This submission is selected to advance.
<span class="usa-checkbox__label-description"
>Check the box to select this submission to advance or for award after all evaluations are completed.</span
></label
>
</div>
<input
id="judging-status-hidden"
type="hidden"
name="submission[judging_status]"
data-submission-details-target="judgingStatusHidden"
/>
<div class="usa-form-group">
<%= form.label :comments, "Comments and notes:", class: "usa-label", for: "#{rand}-comments" %>
<%= form.text_area :comments, class: "usa-textarea", default: @submission.comments, id: "#{rand}-comments" %>
</div>
<button type="submit" name="commit" class="usa-button font-body-2xs text-no-wrap margin-y-2">
Save
</button>
<% end %>
</div>
57 changes: 4 additions & 53 deletions app/views/submissions/_submission_details.html.erb
Original file line number Diff line number Diff line change
@@ -1,53 +1,4 @@
<div data-controller="submission-details">
<% rand = SecureRandom.hex(8) %>
<%= form_with(model: @submission, url: submission_path(@submission), class: "maxw-mobile-lg") do |form| %>
<div class="usa-checkbox" id="eligible-for-evaluation">
<input
class="usa-checkbox__input usa-checkbox__input--tile"
type="checkbox"
id="<%= "#{rand}-judging-status-selected" %>"
value="selected"
<%= if @submission.judging_status == "winner" then "disabled" end %>
<%= "checked" if @submission.judging_status.in?(["selected", "winner"]) %>
data-action="change->submission-details#eligibleCheck"
data-submission-details-target="eligibleCheckbox"
/>
<label class="usa-checkbox__label" for="<%= "#{rand}-judging-status-selected" %>"
>This submission is eligible for evaluation.
<span class="usa-checkbox__label-description"
>Check the box if the submission is pre-screened and is eligible for the evaluation process.</span
></label
>
</div>
<div class="usa-checkbox" id="selected-to-advance">
<input
class="usa-checkbox__input usa-checkbox__input--tile"
id="<%= "#{rand}-judging-status-winner" %>"
type="checkbox"
<%= "disabled" unless @submission.judging_status.in?(["selected", "winner"]) %>
<%= "checked" if @submission.judging_status == "winner" %>
data-action="change->submission-details#selectedCheck"
data-submission-details-target="winnerCheckbox"
/>
<label class="usa-checkbox__label" for="<%= "#{rand}-judging-status-winner" %>"
>This submission is selected to advance.
<span class="usa-checkbox__label-description"
>Check the box to select this submission to advance or for award after all evaluations are completed.</span
></label
>
</div>
<input
id="judging-status-hidden"
type="hidden"
name="submission[judging_status]"
data-submission-details-target="judgingStatusHidden"
/>
<div class="usa-form-group">
<%= form.label :comments, "Comments and notes:", class: "usa-label" %>
<%= form.text_area :comments, class: "usa-textarea", default: @submission.comments %>
</div>
<button type="submit" name="commit" class="usa-button font-body-2xs text-no-wrap margin-y-2">
Save
</button>
<% end %>
</div>
<%= render partial: 'details_form' %>
<% if @submission.judging_status.in?(["selected", "winner"]) %>
<%= render partial: 'submission_evaluation' %>
<% end %>
10 changes: 10 additions & 0 deletions app/views/submissions/_submission_evaluation.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<h2>Submission Evaluation</h2>
<% if @submission.phase.evaluation_form.nil? %>
<%= render 'shared/alert_error', alert_heading: t('alerts.no_evaluation_form.heading'), alert_text: t('alerts.no_evaluation_form.text') %>
<% else %>
<%= render partial: 'assigned_evaluators' %>
<%= render partial: 'available_evaluators' %>
<div class="display-flex flex-justify-end">
<%= link_to "Manage Evaluators", phase_evaluators_path(@submission.phase), class: "margin-y-1" %>
</div>
<% end %>
10 changes: 7 additions & 3 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ en:
already_logged_in_notice: "You are already logged in."
evaluation_form_destroyed: "Evaluation form was successfully destroyed."
evaluation_form_saved: "Evaluation form was saved successfully."
evaluator_submission_assignment_saved: "Submission assignment was saved succesfully."
comments_saved: "Comments saved succesfully."
submission_updated: "Submission was updated successfully."
login_error: "There was an issue with logging in. Please try again."
Expand Down Expand Up @@ -75,11 +76,14 @@ en:
unassigned_submissions: "A list of recused and unassigned submissions. Reassigning a user to a submission will make the submission available for the user to evaluate."
empty_state: "There currently are no assigned submissions to this evaluator. Please assign submissions to this evaluator to view."
assigned:
success: "Evaluator reassigned successfully"
failure: "Failed to reassign evaluator"
success: "Evaluator assigned successfully"
failure: "Failed to assign evaluator"
unassigned:
success: "Evaluator unassigned successfully"
failure: "Failed to unassign evaluator"
failure: "Failed to unassign evaluator"
recused_unassigned:
success: "Recused evaluator unassigned successfully"
failure: "Failed to unassign evaluator"
evaluations:
unique_user_for_evaluation_form_and_submission_error: "already has an evaluation for this form and submission"
unique_evaluator_submission_assignment: "already has an evaluation"
Expand Down
2 changes: 1 addition & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
post 'resend_invite'
end
end
resources :evaluator_submission_assignments, only: [:index, :update]
resources :evaluator_submission_assignments, only: [:index, :update, :create]
end
resources :submissions, only: [:index, :show, :update]

Expand Down
2 changes: 1 addition & 1 deletion db/structure.sql
Original file line number Diff line number Diff line change
Expand Up @@ -1109,7 +1109,7 @@ CREATE TABLE public.submissions (
description_delta text,
brief_description_delta text,
pdf_reference character varying(255),
comments text
comments character varying
);


Expand Down
Loading

0 comments on commit 5baef9a

Please sign in to comment.