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

[179] View Evaluator's Submissions #258

Merged
merged 61 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
7abaa15
245 | Update invited evaluator user setup
emmabjj Nov 4, 2024
2093119
245 | Move evaluator invitation to evaluator user logic
emmabjj Nov 5, 2024
6771cf4
245 | Add check for evaluator's role
emmabjj Nov 5, 2024
ef02ade
245 | Remove duplicate logic and handle in/valid evaluator roles
emmabjj Nov 5, 2024
23e5701
245 | Add successfully removed flash notice back in
emmabjj Nov 5, 2024
27f35d0
245 | Update tests
emmabjj Nov 6, 2024
e64fa23
245 | CPE created automatically, adjust redudant conditional
emmabjj Nov 6, 2024
1d36e0d
179 | UI/Add view for evaluator submissions
emmabjj Nov 7, 2024
d576fa0
179 | Add UI for the unassign modal and js
emmabjj Nov 7, 2024
a91e88a
179 | Add routes
emmabjj Nov 7, 2024
a4a9298
179 | Add evaluator_submissions_assignments association to phase thro…
emmabjj Nov 7, 2024
742af61
179 | Add evaluation submissions controller
emmabjj Nov 7, 2024
44c2db5
179 | Add evaluation status text colors
emmabjj Nov 7, 2024
145886a
179 | Add evaluation status order
emmabjj Nov 7, 2024
16866fb
Merge branch '200_manage_evaluators_list' into 179_evaluator_submissi…
emmabjj Nov 7, 2024
4295f4d
179 | Add evaluator submissions message translations
emmabjj Nov 7, 2024
3f803d3
Merge branch '200_manage_evaluators_list' into 179_evaluator_submissi…
emmabjj Nov 19, 2024
8775c82
179 | Update routes
emmabjj Nov 22, 2024
a68e0cb
179 | Update view and use partials
emmabjj Nov 22, 2024
5c5ad7e
179 | Use update for reassign & unassign
emmabjj Nov 22, 2024
e86b23e
179 | Add recused_unassigned status
emmabjj Nov 22, 2024
fbe433a
179 | Back link partial
emmabjj Nov 22, 2024
3ff0089
179 | Adjust js to use patch update on status reassign/unassign
emmabjj Nov 22, 2024
e7882bf
179 | Add to translations
emmabjj Nov 22, 2024
9c89936
Small updates
emmabjj Nov 22, 2024
01b132f
Small fix
emmabjj Nov 22, 2024
6c32c1d
Merge branch 'dev' into 179_evaluator_submissions_view
emmabjj Nov 22, 2024
1a6531e
Update order by status on evaluation submission assignments
emmabjj Nov 22, 2024
3da992d
Remove unused argument
emmabjj Nov 22, 2024
e541c13
Update ordered by status
emmabjj Nov 22, 2024
ae2870f
77 | Add recused alert for managers on evaluator submission assignmen…
emmabjj Nov 22, 2024
25f0d6d
Merge branch 'dev' into 179_evaluator_submissions_view
emmabjj Nov 22, 2024
8e207e1
179 | Display score for evaluator submission assignments
emmabjj Nov 22, 2024
f0013f6
179 | Adjust SQL statement for status order
emmabjj Nov 22, 2024
6602fb3
179 | Scope score to evaluator's evaluation score
emmabjj Nov 22, 2024
9f44ad8
179 | Recused unassigned cannot be reassign to the submission
emmabjj Nov 22, 2024
2416337
77 | Update recused conditional
emmabjj Nov 25, 2024
d029c20
179 | Update route for evaluation submission assignments
emmabjj Nov 25, 2024
c890db4
179 | Update js to use assignment
emmabjj Nov 25, 2024
01209a4
179 | Update the display score to check for assignment completion
emmabjj Nov 25, 2024
ec365f9
179 | Update ordered by status query
emmabjj Nov 25, 2024
575eda4
179 | Update tests wip
emmabjj Nov 25, 2024
f824247
179 | Remove unused argument in display_score
emmabjj Nov 25, 2024
d99a8b4
179 | Update tests for display scores
emmabjj Nov 25, 2024
28e77ea
Merge branch 'dev' into 179_evaluator_submissions_view
emmabjj Nov 25, 2024
2083129
179 | Update flash, closing date, and error status
emmabjj Dec 3, 2024
f0b582b
179 | Add tests, update statuses, and colors
emmabjj Dec 5, 2024
ffd144d
Rename stat summary for evaluation submission assignments
emmabjj Dec 6, 2024
0edad56
Merge branch '179_evaluator_submissions_view' into 77_recused_submiss…
emmabjj Dec 6, 2024
9123d76
179 | Adjust sorting scope and evaluation status
emmabjj Dec 9, 2024
9d4f6d9
update status colors
stepchud Dec 9, 2024
447a75f
quick syntax fix
emmabjj Dec 9, 2024
3f523f5
Merge remote-tracking branch 'origin/179_evaluator_submissions_view' …
stepchud Dec 9, 2024
3f12ec5
Merge remote-tracking branch 'origin/179_evaluator_submissions_view' …
stepchud Dec 9, 2024
9cac42d
179 | Adjust sorting scope and evaluation status
emmabjj Dec 9, 2024
2224b72
quick syntax fix
emmabjj Dec 9, 2024
b48c371
Merge branch '179_evaluator_submissions_view' into 77_recused_submiss…
emmabjj Dec 9, 2024
a77ad0f
Disable rubocop check on flash before render
emmabjj Dec 9, 2024
f8c5f77
Update .codeclimate.yml rubocop name
stepchud Dec 9, 2024
018dc76
Update app/views/evaluator_submission_assignments/_unassigned_submiss…
stepchud Dec 9, 2024
796252d
Merge pull request #286 from GSA/77_recused_submission_alert
emmabjj Dec 9, 2024
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
46 changes: 39 additions & 7 deletions app/controllers/evaluator_submission_assignments_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,24 @@ class EvaluatorSubmissionAssignmentsController < ApplicationController
before_action :set_assignment, only: [:update]

def index
@evaluator_assignments = @phase.evaluator_submission_assignments.where(user_id: @evaluator.id)
@evaluator_assignments = @phase.evaluator_submission_assignments.includes(:submission).where(user_id: @evaluator.id)
@assigned_submissions = @evaluator_assignments.
where(status: %i[completed in_progress not_started recused]).
where(status: %i[assigned recused]).
includes(:evaluation).
ordered_by_status
@unassigned_submissions = @evaluator_assignments.
where(status: %i[unassigned recused_unassigned]).
ordered_by_status
@submissions_count = @assigned_submissions.group('evaluator_submission_assignments.status').count
@submissions_count = calculate_submissions_count(@assigned_submissions)
end

# update only the status of the evaluation submission assignment to unassign or reassign an evaluator
def update
new_status = params[:status]&.to_sym
new_status = extract_status_from_params

unless valid_status?(new_status)
return render_invalid_status_error
end

if update_assignment_status(new_status)
handle_successful_update(new_status)
Expand All @@ -44,20 +49,47 @@ def set_assignment
@assignment = @phase.evaluator_submission_assignments.find(params[:id])
end

def extract_status_from_params
status = params[:status] || params.dig(:evaluator_submission_assignment, :status)
status&.to_sym
end

def valid_status?(status)
EvaluatorSubmissionAssignment.statuses.keys.map(&:to_sym).include?(status)
end

def render_invalid_status_error
render json: { success: false, message: 'Invalid status' }, status: :unprocessable_entity
end

def update_assignment_status(new_status)
@assignment.update(status: EvaluatorSubmissionAssignment.statuses[new_status])
@assignment.update(status: new_status)
end

def calculate_submissions_count(assignments)
completed = assignments.count { |a| a.evaluation&.completed_at.present? }
in_progress = assignments.count { |a| a.evaluation.present? && a.evaluation.completed_at.nil? }
not_started = assignments.count { |a| a.evaluation.nil? }
total = completed + in_progress + not_started

{
"completed" => completed,
"in_progress" => in_progress,
"not_started" => not_started,
"total" => total
}
end

def handle_successful_update(new_status)
flash.now[:success] = t("evaluator_submission_assignments.#{new_status}.success")
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] } }
end
end

def handle_failed_update(new_status)
flash.now[:error] = t("evaluator_submission_assignments.#{new_status}.failure")
flash[:error] = t("evaluator_submission_assignments.#{new_status}.failure")
respond_to do |format|
format.html { redirect_to_assignment_path }
format.json { render json: { success: false, message: flash[:error] }, status: :unprocessable_entity }
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/evaluators_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def create
if result[:success]
redirect_to phase_evaluators_path(@phase), notice: result[:message]
else
flash.now[:alert] = result[:message]
flash[:alert] = result[:message]
stepchud marked this conversation as resolved.
Show resolved Hide resolved
@evaluator_invitations = @phase.evaluator_invitations
@existing_evaluators = @phase.evaluators
render :index
Expand Down
34 changes: 15 additions & 19 deletions app/helpers/evaluators_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,38 +14,34 @@ def assigned_submissions_count(evaluator, challenge, phase)
if evaluator.is_a?(User)
evaluator.evaluator_submission_assignments.
joins(:submission).
where(submissions: { challenge:, phase: }).
where.not(status: [:unassigned, :recused_unassigned]).
where(submissions: { challenge: challenge, phase: phase }).
where(status: :assigned).
count
else
0
end
end

def evaluation_status(status)
case status.to_sym
when :recused
'text-accent-warm-dark'
def evaluation_submission_assignment_color(assignment)
status = assignment.is_a?(EvaluatorSubmissionAssignment) ? assignment.evaluation_status : assignment.to_sym

case status
when :not_started
'text-secondary-dark'
'bg-secondary-dark'
when :in_progress
'text-orange'
'bg-orange text-black'
when :completed
'text-green'
when :unassigned
'text-accent-cool-darker'
when :recused_unassigned
'text-secondary'
'bg-green'
when :recused, :unassigned, :recused_unassigned
'bg-base'
else
'text-base'
'bg-base'
end
end

def display_score(assignment)
if assignment.completed? && assignment.evaluation&.total_score
assignment.evaluation.total_score
else
'N/A'
end
return 'N/A' unless assignment.evaluation_status == :completed

assignment.evaluation.try(:total_score) || 'N/A'
end
end
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
static targets = ["modal", "confirmButton"]
static targets = ["modal"]
static values = {
phaseId: String,
assignmentId: String
}

connect() {
this.modalTarget.addEventListener('click', this.handleOutsideClick.bind(this))
this.modalTarget.addEventListener('click', this.handleOutsideClick.bind(this));
}

disconnect() {
this.modalTarget.removeEventListener('click', this.handleOutsideClick.bind(this))
this.modalTarget.removeEventListener('click', this.handleOutsideClick.bind(this));
}

open(event) {
Expand All @@ -21,29 +21,23 @@ export default class extends Controller {
this.modalTarget.showModal();
}


close() {
this.modalTarget.close()
this.modalTarget.close();
}

handleOutsideClick(event) {
if (event.target === this.modalTarget) {
this.close()
this.close();
}
}

confirm() {
this.unassignEvaluatorSubmission()
}

setValues(dataset) {
this.assignmentIdValue = dataset.assignmentId;
this.phaseIdValue = dataset.phaseId;
}

unassignEvaluatorSubmission() {
const csrfToken = document.querySelector('meta[name="csrf-token"]').content;

fetch(`/phases/${this.phaseIdValue}/evaluator_submission_assignments/${this.assignmentIdValue}`, {
method: 'PATCH',
headers: {
Expand All @@ -52,7 +46,7 @@ export default class extends Controller {
'Accept': 'application/json'
},
body: JSON.stringify({
status: 'unassigned'
evaluator_submission_assignment: { status: 'unassigned' }
})
})
.then(response => response.json())
Expand Down
54 changes: 38 additions & 16 deletions app/models/evaluator_submission_assignment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,47 @@ class EvaluatorSubmissionAssignment < ApplicationRecord
assigned: 0,
unassigned: 1,
recused: 2,
recused_unassigned: 3
}

def evaluation_status
if assigned?
if evaluation.nil?
:not_started
elsif evaluation.completed_at.nil?
:in_progress
else
:completed
end
else
status.to_sym
end
end

ORDER_VALUES = {
recused: 0,
unassigned: 1,
recused_unassigned: 2,
not_started: 3,
in_progress: 4,
completed: 5,
recused_unassigned: 6
}
completed: 5
}.freeze

def ordering_priority
case evaluation_status
when :recused then ORDER_VALUES[:recused]
when :unassigned then ORDER_VALUES[:unassigned]
when :recused_unassigned then ORDER_VALUES[:recused_unassigned]
when :not_started then ORDER_VALUES[:not_started]
when :in_progress then ORDER_VALUES[:in_progress]
when :completed then ORDER_VALUES[:completed]
end
stepchud marked this conversation as resolved.
Show resolved Hide resolved
end

scope :ordered_by_status, lambda {
order(
Arel.sql(
"CASE evaluator_submission_assignments.status
WHEN #{ActiveRecord::Base.connection.quote(statuses[:recused])} THEN 0
WHEN #{ActiveRecord::Base.connection.quote(statuses[:unassigned])} THEN 1
WHEN #{ActiveRecord::Base.connection.quote(statuses[:recused_unassigned])} THEN 2
WHEN #{ActiveRecord::Base.connection.quote(statuses[:not_started])} THEN 3
WHEN #{ActiveRecord::Base.connection.quote(statuses[:in_progress])} THEN 4
WHEN #{ActiveRecord::Base.connection.quote(statuses[:completed])} THEN 5
ELSE 6
END"
)
)
select('evaluator_submission_assignments.*, evaluations.id AS evaluation_id, evaluations.completed_at').
left_joins(:evaluation).
to_a.
sort_by(&:ordering_priority)
stepchud marked this conversation as resolved.
Show resolved Hide resolved
}
end
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
<div class="tablet:flex-fill">
<div class="display-flex flex-align-center margin-bottom-2 tablet:margin-bottom-0">
<div class="margin-right-2">
<span class="font-sans-3xl text-primary text-bold"><%= @assigned_submissions.count %></span>
<span class="font-sans-3xl text-primary text-bold"><%= @submissions_count["total"] %></span>
</div>
<div>
<h3 class="usa-summary-box__heading text-primary margin-bottom-05" id="summary-box-key-information">
Assigned Submissions
</h3>
<p class="usa-summary-box__text text-primary-darker text-bold">
Evaluations due by <%= @phase.end_date.strftime('%m/%d/%Y') %>
Evaluations due by <%= @phase.evaluation_form.closing_date.strftime('%m/%d/%Y') %>
</p>
</div>
</div>
Expand All @@ -28,7 +28,7 @@
<span class="font-sans-xl text-green text-bold"><%= @submissions_count["completed"] || 0 %></span><br>
<span class="text-base-sm text-green text-bold">Completed</span>
</div>
<div class="text-center margin-right-5">
<div class="text-center margin-right-4">
<span class="font-sans-xl text-orange text-bold"><%= @submissions_count["in_progress"] || 0 %></span><br>
<span class="text-base-sm text-orange text-bold">In Progress</span>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<tr data-evaluator-id="<%= evaluator.id %>" data-evaluator-type="user">
<td data-label="Submission ID" class="text-top text-bold"><%= assignment.submission.id %></td>
<td data-label="Evaluation status">
<span class="text-top text-bold <%= evaluation_status(assignment.status) %>"><%= assignment.status.titleize %></span>
<span class="text-top usa-tag <%= evaluation_submission_assignment_color(assignment) %>"><%= assignment.evaluation_status.to_s.titleize %></span>
</td>
<td data-label="Score" class="text-top text-normal"><%= display_score(assignment) %></td>
<td data-label="">
<div class="display-flex flex-justify-end">
<% if assignment.completed? %>
<% if assignment.evaluation_status == :completed %>
<%= link_to "View Evaluation", submissions_path(@challenge), class: 'usa-button font-body-3xs margin-right-1' %>
<% end %>
<%= button_tag "Unassign", type: 'button', class: 'usa-button usa-button--outline font-body-3xs', data: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@
<div class="usa-modal__footer">
<ul class="usa-button-group">
<li class="usa-button-group__item">
<button type="button" class="usa-button" data-unassign-evaluator-submission-modal-target="confirmButton" data-action="click->unassign-evaluator-submission-modal#confirm">
<button
type="button"
class="usa-button"
data-action="click->unassign-evaluator-submission-modal#unassignEvaluatorSubmission">
Yes
</button>
</li>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
<tr data-evaluator-id="<%= evaluator.id %>" data-evaluator-type="user">
<td data-label="Submission ID" class="text-top text-bold"><%= assignment.submission.id %></td>
<td data-label="Evaluation status">
<span class="text-top text-bold <%= evaluation_status(assignment.status) %>"><%= assignment.status.titleize %></span>
<span class="text-top usa-tag <%= evaluation_submission_assignment_color(assignment) %>"><%= assignment.evaluation_status.to_s.titleize %></span>
</td>
<td data-label="Score" class="text-top text-light"><%= display_score(assignment) %></td>
<td data-label="">
<div class="display-flex flex-justify-end">
<% if assignment.unassigned? %>
<%= button_to "Reassign", phase_evaluator_submission_assignment_path(@phase, assignment),
method: :patch,
params: { status: :not_started, evaluator_id: evaluator.id },
class: 'usa-button usa-button--outline font-body-3xs' %>
params: { status: :assigned, evaluator_id: evaluator.id },
class: 'usa-button usa-button--outline font-body-3xs' %>
<% end %>
</div>
</td>
Expand Down
4 changes: 1 addition & 3 deletions app/views/evaluator_submission_assignments/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@
<h3 class="font-body-lg">Assigned Submissions</h3>
<p><%= t('evaluator_submission_assignments.assigned_submissions') %></p>

<%= render 'submission_summary', assigned_count: @assigned_submissions.count,
submissions_count: @submissions_count,
phase_end_date: @phase.end_date %>
<%= render 'assignment_stats' %>

<% if @assigned_submissions.any? %>
<%= render layout: 'submission_table' do %>
Expand Down
2 changes: 1 addition & 1 deletion app/views/shared/_back_link.html.erb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div class="margin-bottom-2 margin-top-3">
<%= link_to path, class: "usa-link display-inline-flex flex-align-center" do %>
<%= image_tag('images/usa-icons/arrow_back.svg', class: "usa-icon--size-3", alt: "Back to previous page") %>
<span class="margin-left-05 text-primary"><%= 'Back' %></span>
<span class="margin-left-05 text-primary">Back</span>
<% end %>
</div>
2 changes: 1 addition & 1 deletion config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ en:
assigned_submissions: "A list of submissions assigned to the user."
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."
not_started:
assigned:
success: "Evaluator reassigned successfully"
failure: "Failed to reassign evaluator"
unassigned:
Expand Down
Loading
Loading