mirror of
https://github.com/edcommonwealth/sqm-dashboards.git
synced 2026-03-07 21:48:16 -08:00
Add Overall Response Rate
This commit is contained in:
parent
bb6d31ecf1
commit
a785c69c44
14 changed files with 920 additions and 450 deletions
|
|
@ -89,6 +89,26 @@
|
|||
width: 20px;
|
||||
}
|
||||
|
||||
.overall-response-rate-row {
|
||||
width: 55%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
margin-top: -23px;
|
||||
}
|
||||
|
||||
.overall-response-rate-container {
|
||||
padding: 0.4em 0.7em;
|
||||
width: 48%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: $gray-1;
|
||||
@extend .bg-color-gray-3;
|
||||
@extend .border-radius-8;
|
||||
@extend .font-size-14
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 768px){
|
||||
.measure-row-label {
|
||||
width: 170px;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,10 @@ class OverviewController < SqmApplicationController
|
|||
def index
|
||||
@variance_chart_row_presenters = measures.map(&method(:presenter_for_measure))
|
||||
@category_presenters = Category.sorted.map { |category| CategoryPresenter.new(category:) }
|
||||
@student_response_rate_presenter = ResponseRatePresenter.new(focus: :student, school: @school,
|
||||
academic_year: @academic_year)
|
||||
@teacher_response_rate_presenter = ResponseRatePresenter.new(focus: :teacher, school: @school,
|
||||
academic_year: @academic_year)
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
45
app/presenters/response_rate_presenter.rb
Normal file
45
app/presenters/response_rate_presenter.rb
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
class ResponseRatePresenter
|
||||
attr_reader :focus, :academic_year, :school, :survey_items
|
||||
|
||||
def initialize(focus:, academic_year:, school:)
|
||||
@focus = focus
|
||||
@academic_year = academic_year
|
||||
@school = school
|
||||
@survey_items = SurveyItem.student_survey_items if focus == :student
|
||||
@survey_items = SurveyItem.teacher_survey_items if focus == :teacher
|
||||
end
|
||||
|
||||
def date
|
||||
SurveyItemResponse.where(survey_item: survey_items, school:).order(updated_at: :DESC).first&.updated_at || Date.new
|
||||
end
|
||||
|
||||
def percentage
|
||||
cap_at_100(actual_count.to_f / respondents_count.to_f * 100).round
|
||||
end
|
||||
|
||||
def color
|
||||
# Problem: the color (either $gold or $purple) is determined by the scss variable, but the
|
||||
# percentage is decided by the presenter. Therefore the class style must be generated
|
||||
# within this file and not the scss file.
|
||||
# TODO: Fix this.
|
||||
percentage > 75 ? "#49416D" : "#FFC857"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def cap_at_100(value)
|
||||
value > 100 ? 100 : value
|
||||
end
|
||||
|
||||
def actual_count
|
||||
SurveyItemResponse.where(school:, academic_year:,
|
||||
survey_item: survey_items).select(:response_id).distinct.count
|
||||
end
|
||||
|
||||
def respondents_count
|
||||
respondents = Respondent.find_by(school:, academic_year:)
|
||||
count = respondents.total_students if focus == :student
|
||||
count = respondents.total_teachers if focus == :teacher
|
||||
count
|
||||
end
|
||||
end
|
||||
|
|
@ -68,7 +68,7 @@ class SurveyResponsesDataLoader
|
|||
likert_score = row.likert_score(survey_item_id: survey_item.survey_item_id) || next
|
||||
|
||||
unless likert_score.valid_likert_score?
|
||||
puts "Response ID: #{row.response_id}, Likert score: #{likert_score} rejected" unless likert_score == 'NA'
|
||||
puts "Response ID: #{row.response_id}, Likert score: #{likert_score} rejected" unless likert_score == "NA"
|
||||
next
|
||||
end
|
||||
response = row.survey_item_response(survey_item:)
|
||||
|
|
@ -96,7 +96,7 @@ class SurveyResponsesDataLoader
|
|||
def self.get_survey_item_ids_from_headers(headers:)
|
||||
CSV.parse(headers).first
|
||||
.filter(&:present?)
|
||||
.filter { |header| header.start_with? 't-', 's-' }
|
||||
.filter { |header| header.start_with? "t-", "s-" }
|
||||
end
|
||||
|
||||
private_class_method :process_row
|
||||
|
|
|
|||
8
app/views/overview/_response_rate.html.erb
Normal file
8
app/views/overview/_response_rate.html.erb
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<div class="overall-response-rate-container">
|
||||
<div>Response Rates as of <%= response_rate_presenter.date.to_date.strftime("%m/%d/%y") %> </div>
|
||||
<div style="display: flex; justify-content:space-between; width: 100px;">
|
||||
<div><%= response_rate_presenter.focus.capitalize %> </div>
|
||||
<%= render partial: "response_rate_graphic", locals: {response_rate_presenter: response_rate_presenter}, cached: true %>
|
||||
<div><%= response_rate_presenter.percentage %>% </div>
|
||||
</div>
|
||||
</div>
|
||||
35
app/views/overview/_response_rate_graphic.html.erb
Normal file
35
app/views/overview/_response_rate_graphic.html.erb
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<style>
|
||||
/*
|
||||
For some reason, none of the sizing in the pie class works, and it always
|
||||
fills 100% of the containing frame, so the size has to be dictated by .prog
|
||||
*/
|
||||
.prog {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
position: relative;
|
||||
border: 1px solid black;
|
||||
border-radius: 50%;
|
||||
margin-top: 0.2em;
|
||||
}
|
||||
.pie {
|
||||
aspect-ratio: 1;
|
||||
display: inline-grid;
|
||||
place-content: center;
|
||||
margin: 5px;
|
||||
font-size: 25px;
|
||||
font-weight: bold;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
#response-rate-pie-<%= response_rate_presenter.focus %>:before{
|
||||
content: "";
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
inset: 0;
|
||||
background: conic-gradient(<%= response_rate_presenter.color %> calc(<%= response_rate_presenter.percentage %>*1%),#0000 0);
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="prog">
|
||||
<div id="response-rate-pie-<%= response_rate_presenter.focus %>" class="pie"></div>
|
||||
</div>
|
||||
|
|
@ -81,6 +81,12 @@
|
|||
</div>
|
||||
</div>
|
||||
<%= render partial: "quality_framework_indicators", locals: { category_presenters: @category_presenters }, cached: true %>
|
||||
|
||||
<div class="overall-response-rate-row">
|
||||
<%= render partial: "response_rate", locals: {response_rate_presenter: @student_response_rate_presenter}, cached: true %>
|
||||
<%= render partial: "response_rate", locals: {response_rate_presenter: @teacher_response_rate_presenter}, cached: true %>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="card">
|
||||
<h2 class="sub-header-2 mb-4">Distance From Benchmark</h2>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue