Skip to content

Commit

Permalink
Merge branch 'dev' into 74_enter_evaluators_a11y_fix
Browse files Browse the repository at this point in the history
  • Loading branch information
emmabjj authored Jan 7, 2025
2 parents e4ecf73 + 3b89d26 commit ecdf880
Show file tree
Hide file tree
Showing 13 changed files with 635 additions and 99 deletions.
48 changes: 47 additions & 1 deletion app/assets/stylesheets/application.sass.scss
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,52 @@ dialog::backdrop {
background-color: #4d8055;
}

.usa-nav__primary {
button.usa-accordion__button {
&::before,
&::after,
span::after {
display: none !important;
content: none !important;
-webkit-mask: none !important;
mask: none !important;
}

.usa-icon {
width: 1.5rem;
height: 1.5rem;
fill: #005ea2;
vertical-align: middle;
position: relative;
top: -2px;

@media (min-width: 64em) {
margin-left: -16px;
}
}

.icon-up {
display: none;
}

&[aria-expanded="true"] {
.icon-down {
display: none;
}
.icon-up {
display: inline-block;
}
}
}

@media (max-width: 64em) {
a:not(.usa-button):hover {
background-color: #005ea2;
color: white;
}
}
}

.usa-combo-box .border-secondary + input {
border: 1px solid red;
}
}
111 changes: 104 additions & 7 deletions app/controllers/phases_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,27 @@ def index

def submissions
@submissions = @phase.submissions
@submissions_count = @submissions.count
not_started = @submissions.left_outer_joins(:evaluations).
where({ "evaluations.id" => nil }).count
in_progress = @submissions.joins(:evaluations).
select("submissions.id").where({ "evaluations.completed_at" => nil }).distinct.count
completed = @submissions_count - in_progress - not_started
@submissions_by_status = { not_started:, in_progress:, completed: }

set_submission_counts
set_submission_statuses

apply_filters
apply_sorting

@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
end

private
Expand All @@ -26,4 +40,87 @@ def set_phase
@phase = Phase.where(challenge: current_user.challenge_manager_challenges).find(params[:id])
@challenge = @phase.challenge
end

def set_submission_counts
@submissions_count = @submissions.count
@eligible_count = @submissions.eligible_for_evaluation.count
@selected_count = @submissions.winner.count
end

def set_submission_statuses
@not_started = @submissions.left_joins(evaluator_submission_assignments: :evaluation).
where(evaluations: { id: nil }).distinct
@in_progress = @submissions.joins(evaluator_submission_assignments: :evaluation).
where(evaluations: { completed_at: nil }).distinct
@completed = @submissions.joins(evaluator_submission_assignments: :evaluation).
where.not(evaluations: { completed_at: nil }).
where.not(id: @in_progress.select(:id)).distinct
@submissions_by_status = {
not_started: @not_started.count,
in_progress: @in_progress.count,
completed: @completed.count
}
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
end
15 changes: 9 additions & 6 deletions app/javascript/controllers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,6 @@ import { application } from "./application";
import DeleteEvaluatorModalController from "./delete_evaluator_modal_controller";
application.register("delete-evaluator-modal", DeleteEvaluatorModalController);

import UnassignEvaluatorSubmissionModalController from "./unassign_evaluator_submission_modal_controller";
application.register(
"unassign-evaluator-submission-modal",
UnassignEvaluatorSubmissionModalController
);

import EvaluationCriteriaController from "./evaluation_criteria_controller";
application.register("evaluation-criteria", EvaluationCriteriaController);

Expand All @@ -25,5 +19,14 @@ application.register("hotdog", HotdogController);
import SubmissionDetailsController from "./submission_details_controller";
application.register("submission-details", SubmissionDetailsController);

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

import ModalController from "./modal_controller";
application.register("modal", ModalController);

import SortFilterMenuController from "./sort_filter_menu_controller";
application.register("sort-filter-menu", SortFilterMenuController);

import UnassignEvaluatorSubmissionModalController from "./unassign_evaluator_submission_modal_controller";
application.register("unassign-evaluator-submission-modal", UnassignEvaluatorSubmissionModalController);
45 changes: 45 additions & 0 deletions app/javascript/controllers/load_more_controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
static targets = ["container", "loadMoreButton"]
static values = {
page: Number,
totalCount: Number
}

connect() {
this.pageValue = 1
this.checkHasMoreSubmissions()
}

async loadMore() {
this.pageValue++

try {
const url = new URL(window.location.href)
url.searchParams.set('page', this.pageValue)
url.searchParams.set('partial', 'true')

const response = await fetch(url, {
headers: {
'Accept': 'text/html',
'X-Requested-With': 'XMLHttpRequest'
}
})
if (!response.ok) throw new Error('Network response was not ok')

const html = await response.text()
this.containerTarget.insertAdjacentHTML('beforeend', html)
this.checkHasMoreSubmissions()
} catch (error) {
console.error("Error loading more submissions:", error)
}
}

checkHasMoreSubmissions() {
const rows = this.containerTarget.querySelectorAll('tr')
if (rows.length >= this.totalCountValue) {
this.loadMoreButtonTarget.classList.add('display-none')
}
}
}
60 changes: 60 additions & 0 deletions app/javascript/controllers/sort_filter_menu_controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// app/javascript/controllers/sort_filter_menu_controller.js
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
static targets = ["menuItem"]

connect() {
this.updateCheckmarks()
}

toggle(event) {
event.preventDefault()
const clickedItem = event.currentTarget
const filterValue = clickedItem.dataset.filterValue

const currentUrl = new URL(window.location.href)
const [param, value] = filterValue.split('=')

if (currentUrl.searchParams.get(param) === value) {
this.clearAllFilters()
} else {
this.applyFilter(filterValue)
}
}

applyFilter(filterValue) {
const currentUrl = new URL(window.location.href)
const [param, value] = filterValue.split('=')

this.removeExistingParams(currentUrl)
currentUrl.searchParams.set(param, value)
window.location.href = currentUrl.toString()
}

clearAllFilters() {
const currentUrl = new URL(window.location.href)
this.removeExistingParams(currentUrl)
window.location.href = currentUrl.toString()
}

removeExistingParams(url) {
const paramsToRemove = ['status', 'eligible_for_evaluation', 'selected_to_advance', 'sort']
paramsToRemove.forEach(key => {
url.searchParams.delete(key)
})
}

updateCheckmarks() {
const currentUrl = new URL(window.location.href)
this.menuItemTargets.forEach(item => {
const checkmark = item.querySelector('.checkmark')
const [param, value] = item.dataset.filterValue.split('=')
if (currentUrl.searchParams.get(param) === value) {
checkmark.style.display = 'inline'
} else {
checkmark.style.display = 'none'
}
})
}
}
21 changes: 21 additions & 0 deletions app/models/submission.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,25 @@ def eligible_for_evaluation?
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)
direction_sql = direction == :desc ? 'DESC' : 'ASC'

joins(
"LEFT JOIN evaluations ON evaluations.submission_id = submissions.id " \
"AND evaluations.completed_at IS NOT NULL"
).
group('submissions.id').
order(
Arel.sql(
"COALESCE(ROUND(AVG(evaluations.total_score)), 0) #{direction_sql}, " \
"submissions.id #{direction_sql}"
)
)
end
end
Loading

0 comments on commit ecdf880

Please sign in to comment.