chore: show analyze page without errors

This commit is contained in:
Nelson Jovel 2024-01-26 19:07:15 -08:00
parent e4e6a5c7fb
commit b47f8d2f61
84 changed files with 2243 additions and 1792 deletions

View file

@ -7,7 +7,6 @@ module Dashboard
def show def show
@categories = Category.sorted.map { |category| CategoryPresenter.new(category:) } @categories = Category.sorted.map { |category| CategoryPresenter.new(category:) }
puts params
@category = CategoryPresenter.new(category: Category.find_by_slug(params[:id])) @category = CategoryPresenter.new(category: Category.find_by_slug(params[:id]))
end end
end end

View file

@ -45,7 +45,7 @@ module Dashboard
@empty_dataset ||= Hash.new do |memo, (school, academic_year)| @empty_dataset ||= Hash.new do |memo, (school, academic_year)|
memo[[school, academic_year]] = measures.none? do |measure| memo[[school, academic_year]] = measures.none? do |measure|
response_rate = measure.subcategory.response_rate(school:, academic_year:) response_rate = measure.subcategory.response_rate(school:, academic_year:)
response_rate.meets_student_threshold || response_rate.meets_teacher_threshold || measure.sufficient_admin_data?(school:, academic_year:) response_rate.meets_student_threshold? || response_rate.meets_teacher_threshold? || measure.sufficient_admin_data?(school:, academic_year:)
end end
end end
@ -56,7 +56,7 @@ module Dashboard
@empty_survey_dataset ||= Hash.new do |memo, (school, academic_year)| @empty_survey_dataset ||= Hash.new do |memo, (school, academic_year)|
memo[[school, academic_year]] = measures.none? do |measure| memo[[school, academic_year]] = measures.none? do |measure|
response_rate = measure.subcategory.response_rate(school:, academic_year:) response_rate = measure.subcategory.response_rate(school:, academic_year:)
response_rate.meets_student_threshold || response_rate.meets_teacher_threshold response_rate.meets_student_threshold? || response_rate.meets_teacher_threshold?
end end
end end
@empty_survey_dataset[[school, academic_year]] @empty_survey_dataset[[school, academic_year]]

View file

@ -3,16 +3,16 @@
module Dashboard module Dashboard
module HeaderHelper module HeaderHelper
def link_to_overview(district:, school:, academic_year:) def link_to_overview(district:, school:, academic_year:)
"/districts/#{district.slug}/schools/#{school.slug}/overview?year=#{academic_year.range}" district_school_overview_index_path(district, school, year: academic_year.range)
end end
def link_to_browse(district:, school:, academic_year:) def link_to_browse(district:, school:, academic_year:)
"/districts/#{district.slug}/schools/#{school.slug}/browse/teachers-leadership?year=#{academic_year.range}" district_school_category_path(district, school, { year: academic_year.range, id: "teachers-leadership" })
end end
def link_to_analyze(district:, school:, academic_year:) def link_to_analyze(district:, school:, academic_year:)
year = academic_year.range year = academic_year.range
"/districts/#{district.slug}/schools/#{school.slug}/analyze?year=#{year}&category=1&academic_years=#{year}" district_school_analyze_index_path(district, school, { year:, category: 1, academic_years: year })
end end
def district_url_for(district:, academic_year:) def district_url_for(district:, academic_year:)

View file

@ -1,85 +1,87 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
class BarPresenter module Analyze
include AnalyzeHelper class BarPresenter
attr_reader :score, :x_position, :academic_year, :measure_id, :measure, :color include AnalyzeHelper
attr_reader :score, :x_position, :academic_year, :measure_id, :measure, :color
MINIMUM_BAR_HEIGHT = 2 MINIMUM_BAR_HEIGHT = 2
def initialize(measure:, academic_year:, score:, x_position:, color:) def initialize(measure:, academic_year:, score:, x_position:, color:)
@score = score @score = score
@x_position = x_position @x_position = x_position
@academic_year = academic_year @academic_year = academic_year
@measure = measure @measure = measure
@measure_id = measure.measure_id @measure_id = measure.measure_id
@color = color @color = color
end
def y_offset
benchmark_height = analyze_zone_height * 2
case zone.type
when :ideal, :approval
benchmark_height - bar_height_percentage
else
benchmark_height
end end
end
def bar_color def y_offset
"fill-#{zone.type}" benchmark_height = analyze_zone_height * 2
end case zone.type
when :ideal, :approval
benchmark_height - bar_height_percentage
else
benchmark_height
end
end
def bar_height_percentage def bar_color
bar_height = send("#{zone.type}_bar_height_percentage") || 0 "fill-#{zone.type}"
enforce_minimum_height(bar_height:) end
end
def percentage def bar_height_percentage
low_benchmark = zone.low_benchmark bar_height = send("#{zone.type}_bar_height_percentage") || 0
(score.average - low_benchmark) / (zone.high_benchmark - low_benchmark) enforce_minimum_height(bar_height:)
end end
def zone def percentage
zones = Zones.new( low_benchmark = zone.low_benchmark
watch_low_benchmark: measure.watch_low_benchmark, (score.average - low_benchmark) / (zone.high_benchmark - low_benchmark)
growth_low_benchmark: measure.growth_low_benchmark, end
approval_low_benchmark: measure.approval_low_benchmark,
ideal_low_benchmark: measure.ideal_low_benchmark
)
zones.zone_for_score(score.average)
end
def average def zone
average = score.average || 0 zones = Zones.new(
watch_low_benchmark: measure.watch_low_benchmark,
growth_low_benchmark: measure.growth_low_benchmark,
approval_low_benchmark: measure.approval_low_benchmark,
ideal_low_benchmark: measure.ideal_low_benchmark
)
zones.zone_for_score(score.average)
end
average.round(6) def average
end average = score.average || 0
private average.round(6)
end
def enforce_minimum_height(bar_height:) private
bar_height < MINIMUM_BAR_HEIGHT ? MINIMUM_BAR_HEIGHT : bar_height
end
def ideal_bar_height_percentage def enforce_minimum_height(bar_height:)
(percentage * zone_height_percentage + zone_height_percentage) * 100 bar_height < MINIMUM_BAR_HEIGHT ? MINIMUM_BAR_HEIGHT : bar_height
end end
def approval_bar_height_percentage def ideal_bar_height_percentage
(percentage * zone_height_percentage) * 100 (percentage * zone_height_percentage + zone_height_percentage) * 100
end end
def growth_bar_height_percentage def approval_bar_height_percentage
((1 - percentage) * zone_height_percentage) * 100 (percentage * zone_height_percentage) * 100
end end
def watch_bar_height_percentage def growth_bar_height_percentage
((1 - percentage) * zone_height_percentage + zone_height_percentage) * 100 ((1 - percentage) * zone_height_percentage) * 100
end end
def warning_bar_height_percentage def watch_bar_height_percentage
((1 - percentage) * zone_height_percentage + zone_height_percentage + zone_height_percentage) * 100 ((1 - percentage) * zone_height_percentage + zone_height_percentage) * 100
end
def warning_bar_height_percentage
((1 - percentage) * zone_height_percentage + zone_height_percentage + zone_height_percentage) * 100
end
end end
end end
end end

View file

@ -1,19 +1,21 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
class AllData module Graph
include Analyze::Graph::Column class AllData
def to_s include Analyze::Graph::Column
"All Data" def to_s
end "All Data"
end
def slug def slug
"all-data" "all-data"
end end
def columns def columns
[AllStudent, AllTeacher, AllAdmin, GroupedBarColumnPresenter] [AllStudent, AllTeacher, AllAdmin, GroupedBarColumnPresenter]
end
end end
end end
end end

View file

@ -1,37 +1,39 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
class AllAdmin < GroupedBarColumnPresenter module Column
def label class AllAdmin < GroupedBarColumnPresenter
%w[All Admin] def label
end %w[All Admin]
def basis
"admin data"
end
def show_irrelevancy_message?
!measure.includes_admin_data_items?
end
def show_insufficient_data_message?
!academic_years.any? do |year|
measure.sufficient_admin_data?(school:, academic_year: year)
end end
end
def insufficiency_message def basis
["data not", "available"] "admin data"
end end
def score(year_index) def show_irrelevancy_message?
measure.admin_score(school:, academic_year: academic_years[year_index]) !measure.includes_admin_data_items?
end end
def type def show_insufficient_data_message?
:admin !academic_years.any? do |year|
measure.sufficient_admin_data?(school:, academic_year: year)
end
end
def insufficiency_message
["data not", "available"]
end
def score(year_index)
measure.admin_score(school:, academic_year: academic_years[year_index])
end
def type
:admin
end
end end
end end
end end

View file

@ -1,31 +1,33 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
class AllStudent < GroupedBarColumnPresenter module Column
def label class AllStudent < GroupedBarColumnPresenter
%w[All Students] def label
end %w[All Students]
def show_irrelevancy_message?
!measure.includes_student_survey_items?
end
def show_insufficient_data_message?
scores = academic_years.map do |year|
measure.score(school:, academic_year: year)
end end
scores.all? { |score| !score.meets_student_threshold? } def show_irrelevancy_message?
end !measure.includes_student_survey_items?
end
def score(year_index) def show_insufficient_data_message?
measure.student_score(school:, academic_year: academic_years[year_index]) scores = academic_years.map do |year|
end measure.score(school:, academic_year: year)
end
def type scores.all? { |score| !score.meets_student_threshold? }
:student end
def score(year_index)
measure.student_score(school:, academic_year: academic_years[year_index])
end
def type
:student
end
end end
end end
end end

View file

@ -1,45 +1,47 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
class AllSurveyData < GroupedBarColumnPresenter module Column
def label class AllSurveyData < GroupedBarColumnPresenter
%w[Survey Data] def label
end %w[Survey Data]
def show_irrelevancy_message?
false
end
def show_insufficient_data_message?
scores = academic_years.map do |year|
combined_score(school:, academic_year: year)
end end
scores.all? { |score| !score.meets_student_threshold? && !score.meets_teacher_threshold? } def show_irrelevancy_message?
end false
end
def score(year_index) def show_insufficient_data_message?
combined_score(school:, academic_year: academic_years[year_index]) scores = academic_years.map do |year|
end combined_score(school:, academic_year: year)
end
def type scores.all? { |score| !score.meets_student_threshold? && !score.meets_teacher_threshold? }
:all_survey_data end
end
private def score(year_index)
combined_score(school:, academic_year: academic_years[year_index])
end
def combined_score(school:, academic_year:) def type
teacher_score = measure.teacher_score(school:, academic_year:) :all_survey_data
student_score = measure.student_score(school:, academic_year:) end
averages = [] private
averages << student_score.average unless student_score.average.nil?
averages << teacher_score.average unless teacher_score.average.nil? def combined_score(school:, academic_year:)
average = averages.average if averages.length > 0 teacher_score = measure.teacher_score(school:, academic_year:)
combined_score = Score.new(average:, meets_student_threshold: student_score.meets_student_threshold, student_score = measure.student_score(school:, academic_year:)
meets_teacher_threshold: teacher_score.meets_teacher_threshold)
averages = []
averages << student_score.average unless student_score.average.nil?
averages << teacher_score.average unless teacher_score.average.nil?
average = averages.average if averages.length > 0
combined_score = Score.new(average:, meets_student_threshold: student_score.meets_student_threshold,
meets_teacher_threshold: teacher_score.meets_teacher_threshold)
end
end end
end end
end end

View file

@ -1,40 +1,42 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
class AllTeacher < GroupedBarColumnPresenter module Column
def label class AllTeacher < GroupedBarColumnPresenter
%w[All Teachers] def label
end %w[All Teachers]
def basis
"teacher surveys"
end
def show_irrelevancy_message?
!measure.includes_teacher_survey_items?
end
def show_insufficient_data_message?
scores = academic_years.map do |year|
measure.score(school:, academic_year: year)
end end
scores.all? { |score| !score.meets_teacher_threshold? } def basis
end "teacher surveys"
end
def score(year_index) def show_irrelevancy_message?
measure.teacher_score(school:, academic_year: academic_years[year_index]) !measure.includes_teacher_survey_items?
end end
def type def show_insufficient_data_message?
:teacher scores = academic_years.map do |year|
end measure.score(school:, academic_year: year)
end
def n_size(year_index) scores.all? { |score| !score.meets_teacher_threshold? }
SurveyItemResponse.where(survey_item: measure.teacher_survey_items, school:, end
academic_year: academic_years[year_index]).select(:response_id).distinct.count
def score(year_index)
measure.teacher_score(school:, academic_year: academic_years[year_index])
end
def type
:teacher
end
def n_size(year_index)
SurveyItemResponse.where(survey_item: measure.teacher_survey_items, school:,
academic_year: academic_years[year_index]).select(:response_id).distinct.count
end
end end
end end
end end

View file

@ -1,30 +1,32 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module EllColumn module Column
class Ell < GroupedBarColumnPresenter module EllColumn
include Analyze::Graph::Column::EllColumn::ScoreForEll class Ell < GroupedBarColumnPresenter
include Analyze::Graph::Column::EllColumn::EllCount include Analyze::Graph::Column::EllColumn::ScoreForEll
def label include Analyze::Graph::Column::EllColumn::EllCount
%w[ELL] def label
end %w[ELL]
end
def basis def basis
"student" "student"
end end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def ell def ell
::Ell.find_by_slug "ell" ::Ell.find_by_slug "ell"
end
end end
end end
end end

View file

@ -1,15 +1,19 @@
module Analyze # frozen_string_literal: true
module Graph
module Column
module EllColumn
module EllCount
def type
:student
end
def n_size(year_index) module Dashboard
SurveyItemResponse.where(ell:, survey_item: measure.student_survey_items, school:, grade: grades(year_index), module Analyze
academic_year: academic_years[year_index]).select(:response_id).distinct.count module Graph
module Column
module EllColumn
module EllCount
def type
:student
end
def n_size(year_index)
SurveyItemResponse.where(ell:, survey_item: measure.student_survey_items, school:, grade: grades(year_index),
academic_year: academic_years[year_index]).select(:response_id).distinct.count
end
end end
end end
end end

View file

@ -1,30 +1,32 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module EllColumn module Column
class NotEll < GroupedBarColumnPresenter module EllColumn
include Analyze::Graph::Column::EllColumn::ScoreForEll class NotEll < GroupedBarColumnPresenter
include Analyze::Graph::Column::EllColumn::EllCount include Analyze::Graph::Column::EllColumn::ScoreForEll
def label include Analyze::Graph::Column::EllColumn::EllCount
["Not ELL"] def label
end ["Not ELL"]
end
def basis def basis
"student" "student"
end end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def ell def ell
::Ell.find_by_slug "not-ell" Ell.find_by_slug "not-ell"
end
end end
end end
end end

View file

@ -1,38 +1,42 @@
module Analyze # frozen_string_literal: true
module Graph
module Column
module EllColumn
module ScoreForEll
def score(year_index)
academic_year = academic_years[year_index]
meets_student_threshold = sufficient_student_responses?(academic_year:)
return Score::NIL_SCORE unless meets_student_threshold
averages = SurveyItemResponse.averages_for_ell(measure.student_survey_items, school, academic_year, module Dashboard
ell) module Analyze
average = bubble_up_averages(averages:).round(2) module Graph
module Column
module EllColumn
module ScoreForEll
def score(year_index)
academic_year = academic_years[year_index]
meets_student_threshold = sufficient_student_responses?(academic_year:)
return Score::NIL_SCORE unless meets_student_threshold
Score.new(average:, averages = SurveyItemResponse.averages_for_ell(measure.student_survey_items, school, academic_year,
meets_teacher_threshold: false, ell)
meets_student_threshold:, average = bubble_up_averages(averages:).round(2)
meets_admin_data_threshold: false)
end
def bubble_up_averages(averages:) Score.new(average:,
measure.student_scales.map do |scale| meets_teacher_threshold: false,
scale.survey_items.map do |survey_item| meets_student_threshold:,
averages[survey_item] meets_admin_data_threshold: false)
end
def bubble_up_averages(averages:)
measure.student_scales.map do |scale|
scale.survey_items.map do |survey_item|
averages[survey_item]
end.remove_blanks.average
end.remove_blanks.average end.remove_blanks.average
end.remove_blanks.average end
end
def sufficient_student_responses?(academic_year:) def sufficient_student_responses?(academic_year:)
return false unless measure.subcategory.response_rate(school:, academic_year:).meets_student_threshold? return false unless measure.subcategory.response_rate(school:, academic_year:).meets_student_threshold?
yearly_counts = SurveyItemResponse.where(school:, academic_year:, yearly_counts = SurveyItemResponse.where(school:, academic_year:,
ell:, survey_item: measure.student_survey_items).group(:ell).select(:response_id).distinct(:response_id).count ell:, survey_item: measure.student_survey_items).group(:ell).select(:response_id).distinct(:response_id).count
yearly_counts.any? do |count| yearly_counts.any? do |count|
count[1] >= 10 count[1] >= 10
end
end end
end end
end end

View file

@ -1,30 +1,32 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module EllColumn module Column
class Unknown < GroupedBarColumnPresenter module EllColumn
include Analyze::Graph::Column::EllColumn::ScoreForEll class Unknown < GroupedBarColumnPresenter
include Analyze::Graph::Column::EllColumn::EllCount include Analyze::Graph::Column::EllColumn::ScoreForEll
def label include Analyze::Graph::Column::EllColumn::EllCount
%w[Unknown] def label
end %w[Unknown]
end
def basis def basis
"student" "student"
end end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def ell def ell
::Ell.find_by_slug "unknown" Ell.find_by_slug "unknown"
end
end end
end end
end end

View file

@ -1,30 +1,32 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module GenderColumn module Column
class Female < GroupedBarColumnPresenter module GenderColumn
include Analyze::Graph::Column::GenderColumn::ScoreForGender class Female < GroupedBarColumnPresenter
include Analyze::Graph::Column::GenderColumn::GenderCount include Analyze::Graph::Column::GenderColumn::ScoreForGender
def label include Analyze::Graph::Column::GenderColumn::GenderCount
%w[Female] def label
end %w[Female]
end
def basis def basis
"student" "student"
end end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def gender def gender
::Gender.find_by_qualtrics_code 1 ::Gender.find_by_qualtrics_code 1
end
end end
end end
end end

View file

@ -1,15 +1,19 @@
module Analyze # frozen_string_literal: true
module Graph
module Column
module GenderColumn
module GenderCount
def type
:student
end
def n_size(year_index) module Dashboard
SurveyItemResponse.where(gender:, survey_item: measure.student_survey_items, school:, grade: grades(year_index), module Analyze
academic_year: academic_years[year_index]).select(:response_id).distinct.count module Graph
module Column
module GenderColumn
module GenderCount
def type
:student
end
def n_size(year_index)
SurveyItemResponse.where(gender:, survey_item: measure.student_survey_items, school:, grade: grades(year_index),
academic_year: academic_years[year_index]).select(:response_id).distinct.count
end
end end
end end
end end

View file

@ -1,30 +1,32 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module GenderColumn module Column
class Male < GroupedBarColumnPresenter module GenderColumn
include Analyze::Graph::Column::GenderColumn::ScoreForGender class Male < GroupedBarColumnPresenter
include Analyze::Graph::Column::GenderColumn::GenderCount include Analyze::Graph::Column::GenderColumn::ScoreForGender
def label include Analyze::Graph::Column::GenderColumn::GenderCount
%w[Male] def label
end %w[Male]
end
def basis def basis
"student" "student"
end end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def gender def gender
::Gender.find_by_qualtrics_code 2 ::Gender.find_by_qualtrics_code 2
end
end end
end end
end end

View file

@ -1,30 +1,32 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module GenderColumn module Column
class NonBinary < GroupedBarColumnPresenter module GenderColumn
include Analyze::Graph::Column::GenderColumn::ScoreForGender class NonBinary < GroupedBarColumnPresenter
include Analyze::Graph::Column::GenderColumn::GenderCount include Analyze::Graph::Column::GenderColumn::ScoreForGender
def label include Analyze::Graph::Column::GenderColumn::GenderCount
%w[Non-Binary] def label
end %w[Non-Binary]
end
def basis def basis
"student" "student"
end end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def gender def gender
::Gender.find_by_qualtrics_code 4 ::Gender.find_by_qualtrics_code 4
end
end end
end end
end end

View file

@ -1,38 +1,42 @@
module Analyze # frozen_string_literal: true
module Graph
module Column
module GenderColumn
module ScoreForGender
def score(year_index)
academic_year = academic_years[year_index]
meets_student_threshold = sufficient_student_responses?(academic_year:)
return Score::NIL_SCORE unless meets_student_threshold
averages = SurveyItemResponse.averages_for_gender(measure.student_survey_items, school, academic_year, module Dashboard
gender) module Analyze
average = bubble_up_averages(averages:).round(2) module Graph
module Column
module GenderColumn
module ScoreForGender
def score(year_index)
academic_year = academic_years[year_index]
meets_student_threshold = sufficient_student_responses?(academic_year:)
return Score::NIL_SCORE unless meets_student_threshold
Score.new(average:, averages = SurveyItemResponse.averages_for_gender(measure.student_survey_items, school, academic_year,
meets_teacher_threshold: false, gender)
meets_student_threshold:, average = bubble_up_averages(averages:).round(2)
meets_admin_data_threshold: false)
end
def bubble_up_averages(averages:) Score.new(average:,
measure.student_scales.map do |scale| meets_teacher_threshold: false,
scale.survey_items.map do |survey_item| meets_student_threshold:,
averages[survey_item] meets_admin_data_threshold: false)
end
def bubble_up_averages(averages:)
measure.student_scales.map do |scale|
scale.survey_items.map do |survey_item|
averages[survey_item]
end.remove_blanks.average
end.remove_blanks.average end.remove_blanks.average
end.remove_blanks.average end
end
def sufficient_student_responses?(academic_year:) def sufficient_student_responses?(academic_year:)
return false unless measure.subcategory.response_rate(school:, academic_year:).meets_student_threshold? return false unless measure.subcategory.response_rate(school:, academic_year:).meets_student_threshold?
yearly_counts = SurveyItemResponse.where(school:, academic_year:, yearly_counts = SurveyItemResponse.where(school:, academic_year:,
gender:, survey_item: measure.student_survey_items).group(:gender).select(:response_id).distinct(:response_id).count gender:, survey_item: measure.student_survey_items).group(:gender).select(:response_id).distinct(:response_id).count
yearly_counts.any? do |count| yearly_counts.any? do |count|
count[1] >= 10 count[1] >= 10
end
end end
end end
end end

View file

@ -1,30 +1,32 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module GenderColumn module Column
class Unknown < GroupedBarColumnPresenter module GenderColumn
include Analyze::Graph::Column::GenderColumn::ScoreForGender class Unknown < GroupedBarColumnPresenter
include Analyze::Graph::Column::GenderColumn::GenderCount include Analyze::Graph::Column::GenderColumn::ScoreForGender
def label include Analyze::Graph::Column::GenderColumn::GenderCount
%w[Unknown] def label
end %w[Unknown]
end
def basis def basis
"student" "student"
end end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def gender def gender
::Gender.find_by_qualtrics_code 99 ::Gender.find_by_qualtrics_code 99
end
end end
end end
end end

View file

@ -1,30 +1,32 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module Grade module Column
class Eight < GroupedBarColumnPresenter module Grade
include Analyze::Graph::Column::Grade::ScoreForGrade class Eight < GroupedBarColumnPresenter
include Analyze::Graph::Column::Grade::GradeCount include Analyze::Graph::Column::Grade::ScoreForGrade
def label include Analyze::Graph::Column::Grade::GradeCount
%w[Grade 8] def label
end %w[Grade 8]
end
def basis def basis
"student" "student"
end end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def grade def grade
8 8
end
end end
end end
end end

View file

@ -1,30 +1,32 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module Grade module Column
class Eleven < GroupedBarColumnPresenter module Grade
include Analyze::Graph::Column::Grade::ScoreForGrade class Eleven < GroupedBarColumnPresenter
include Analyze::Graph::Column::Grade::GradeCount include Analyze::Graph::Column::Grade::ScoreForGrade
def label include Analyze::Graph::Column::Grade::GradeCount
%w[Grade 11] def label
end %w[Grade 11]
end
def basis def basis
"student" "student"
end end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def grade def grade
11 11
end
end end
end end
end end

View file

@ -1,30 +1,32 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module Grade module Column
class Five < GroupedBarColumnPresenter module Grade
include Analyze::Graph::Column::Grade::ScoreForGrade class Five < GroupedBarColumnPresenter
include Analyze::Graph::Column::Grade::GradeCount include Analyze::Graph::Column::Grade::ScoreForGrade
def label include Analyze::Graph::Column::Grade::GradeCount
%w[Grade 5] def label
end %w[Grade 5]
end
def basis def basis
"student" "student"
end end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def grade def grade
5 5
end
end end
end end
end end

View file

@ -1,30 +1,32 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module Grade module Column
class Four < GroupedBarColumnPresenter module Grade
include Analyze::Graph::Column::Grade::ScoreForGrade class Four < GroupedBarColumnPresenter
include Analyze::Graph::Column::Grade::GradeCount include Analyze::Graph::Column::Grade::ScoreForGrade
def label include Analyze::Graph::Column::Grade::GradeCount
%w[Grade 4] def label
end %w[Grade 4]
end
def basis def basis
"student" "student"
end end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def grade def grade
4 4
end
end end
end end
end end

View file

@ -1,15 +1,19 @@
module Analyze # frozen_string_literal: true
module Graph
module Column
module Grade
module GradeCount
def type
:student
end
def n_size(year_index) module Dashboard
SurveyItemResponse.where(grade:, survey_item: measure.student_survey_items, school:, module Analyze
academic_year: academic_years[year_index]).select(:response_id).distinct.count module Graph
module Column
module Grade
module GradeCount
def type
:student
end
def n_size(year_index)
SurveyItemResponse.where(grade:, survey_item: measure.student_survey_items, school:,
academic_year: academic_years[year_index]).select(:response_id).distinct.count
end
end end
end end
end end

View file

@ -1,30 +1,32 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module Grade module Column
class Nine < GroupedBarColumnPresenter module Grade
include Analyze::Graph::Column::Grade::ScoreForGrade class Nine < GroupedBarColumnPresenter
include Analyze::Graph::Column::Grade::GradeCount include Analyze::Graph::Column::Grade::ScoreForGrade
def label include Analyze::Graph::Column::Grade::GradeCount
%w[Grade 9] def label
end %w[Grade 9]
end
def basis def basis
"student" "student"
end end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def grade def grade
9 9
end
end end
end end
end end

View file

@ -1,30 +1,32 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module Grade module Column
class One < GroupedBarColumnPresenter module Grade
include Analyze::Graph::Column::Grade::ScoreForGrade class One < GroupedBarColumnPresenter
include Analyze::Graph::Column::Grade::GradeCount include Analyze::Graph::Column::Grade::ScoreForGrade
def label include Analyze::Graph::Column::Grade::GradeCount
%w[Grade 1] def label
end %w[Grade 1]
end
def basis def basis
"student" "student"
end end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def grade def grade
1 1
end
end end
end end
end end

View file

@ -1,38 +1,42 @@
module Analyze # frozen_string_literal: true
module Graph
module Column
module Grade
module ScoreForGrade
def score(year_index)
academic_year = academic_years[year_index]
meets_student_threshold = sufficient_student_responses?(academic_year:)
return Score::NIL_SCORE unless meets_student_threshold
averages = SurveyItemResponse.averages_for_grade(measure.student_survey_items, school, module Dashboard
academic_year, grade) module Analyze
average = bubble_up_averages(averages:).round(2) module Graph
module Column
module Grade
module ScoreForGrade
def score(year_index)
academic_year = academic_years[year_index]
meets_student_threshold = sufficient_student_responses?(academic_year:)
return Score::NIL_SCORE unless meets_student_threshold
Score.new(average:, averages = SurveyItemResponse.averages_for_grade(measure.student_survey_items, school,
meets_teacher_threshold: false, academic_year, grade)
meets_student_threshold:, average = bubble_up_averages(averages:).round(2)
meets_admin_data_threshold: false)
end
def bubble_up_averages(averages:) Score.new(average:,
measure.student_scales.map do |scale| meets_teacher_threshold: false,
scale.survey_items.map do |survey_item| meets_student_threshold:,
averages[survey_item] meets_admin_data_threshold: false)
end
def bubble_up_averages(averages:)
measure.student_scales.map do |scale|
scale.survey_items.map do |survey_item|
averages[survey_item]
end.remove_blanks.average
end.remove_blanks.average end.remove_blanks.average
end.remove_blanks.average end
end
def sufficient_student_responses?(academic_year:) def sufficient_student_responses?(academic_year:)
return false unless measure.subcategory.response_rate(school:, academic_year:).meets_student_threshold? return false unless measure.subcategory.response_rate(school:, academic_year:).meets_student_threshold?
yearly_counts = SurveyItemResponse.where(school:, academic_year:, yearly_counts = SurveyItemResponse.where(school:, academic_year:,
survey_item: measure.student_survey_items).group(:grade).select(:response_id).distinct(:response_id).count survey_item: measure.student_survey_items).group(:grade).select(:response_id).distinct(:response_id).count
yearly_counts.any? do |count| yearly_counts.any? do |count|
count[1] >= 10 count[1] >= 10
end
end end
end end
end end

View file

@ -1,30 +1,32 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module Grade module Column
class Seven < GroupedBarColumnPresenter module Grade
include Analyze::Graph::Column::Grade::ScoreForGrade class Seven < GroupedBarColumnPresenter
include Analyze::Graph::Column::Grade::GradeCount include Analyze::Graph::Column::Grade::ScoreForGrade
def label include Analyze::Graph::Column::Grade::GradeCount
%w[Grade 7] def label
end %w[Grade 7]
end
def basis def basis
"student" "student"
end end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def grade def grade
7 7
end
end end
end end
end end

View file

@ -1,30 +1,32 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module Grade module Column
class Six < GroupedBarColumnPresenter module Grade
include Analyze::Graph::Column::Grade::ScoreForGrade class Six < GroupedBarColumnPresenter
include Analyze::Graph::Column::Grade::GradeCount include Analyze::Graph::Column::Grade::ScoreForGrade
def label include Analyze::Graph::Column::Grade::GradeCount
%w[Grade 6] def label
end %w[Grade 6]
end
def basis def basis
"student" "student"
end end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def grade def grade
6 6
end
end end
end end
end end

View file

@ -1,30 +1,32 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module Grade module Column
class Ten < GroupedBarColumnPresenter module Grade
include Analyze::Graph::Column::Grade::ScoreForGrade class Ten < GroupedBarColumnPresenter
include Analyze::Graph::Column::Grade::GradeCount include Analyze::Graph::Column::Grade::ScoreForGrade
def label include Analyze::Graph::Column::Grade::GradeCount
%w[Grade 10] def label
end %w[Grade 10]
end
def basis def basis
"student" "student"
end end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def grade def grade
10 10
end
end end
end end
end end

View file

@ -1,30 +1,32 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module Grade module Column
class Three < GroupedBarColumnPresenter module Grade
include Analyze::Graph::Column::Grade::ScoreForGrade class Three < GroupedBarColumnPresenter
include Analyze::Graph::Column::Grade::GradeCount include Analyze::Graph::Column::Grade::ScoreForGrade
def label include Analyze::Graph::Column::Grade::GradeCount
%w[Grade 3] def label
end %w[Grade 3]
end
def basis def basis
"student" "student"
end end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def grade def grade
3 3
end
end end
end end
end end

View file

@ -1,30 +1,32 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module Grade module Column
class Twelve < GroupedBarColumnPresenter module Grade
include Analyze::Graph::Column::Grade::ScoreForGrade class Twelve < GroupedBarColumnPresenter
include Analyze::Graph::Column::Grade::GradeCount include Analyze::Graph::Column::Grade::ScoreForGrade
def label include Analyze::Graph::Column::Grade::GradeCount
%w[Grade 12] def label
end %w[Grade 12]
end
def basis def basis
"student" "student"
end end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def grade def grade
12 12
end
end end
end end
end end

View file

@ -1,30 +1,32 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module Grade module Column
class Two < GroupedBarColumnPresenter module Grade
include Analyze::Graph::Column::Grade::ScoreForGrade class Two < GroupedBarColumnPresenter
include Analyze::Graph::Column::Grade::GradeCount include Analyze::Graph::Column::Grade::ScoreForGrade
def label include Analyze::Graph::Column::Grade::GradeCount
%w[Grade 2] def label
end %w[Grade 2]
end
def basis def basis
"student" "student"
end end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def grade def grade
2 2
end
end end
end end
end end

View file

@ -1,30 +1,32 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module Grade module Column
class Zero < GroupedBarColumnPresenter module Grade
include Analyze::Graph::Column::Grade::ScoreForGrade class Zero < GroupedBarColumnPresenter
include Analyze::Graph::Column::Grade::GradeCount include Analyze::Graph::Column::Grade::ScoreForGrade
def label include Analyze::Graph::Column::Grade::GradeCount
%w[Kindergarten] def label
end %w[Kindergarten]
end
def basis def basis
"student" "student"
end end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def grade def grade
0 0
end
end end
end end
end end

View file

@ -1,170 +1,172 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
class GroupedBarColumnPresenter module Column
include AnalyzeHelper class GroupedBarColumnPresenter
include AnalyzeHelper
attr_reader :measure_name, :measure_id, :category, :position, :measure, :school, :academic_years, attr_reader :measure_name, :measure_id, :category, :position, :measure, :school, :academic_years,
:number_of_columns :number_of_columns
def initialize(measure:, school:, academic_years:, position:, number_of_columns:) def initialize(measure:, school:, academic_years:, position:, number_of_columns:)
@measure = measure @measure = measure
@measure_name = @measure.name @measure_name = @measure.name
@measure_id = @measure.measure_id @measure_id = @measure.measure_id
@category = @measure.subcategory.category @category = @measure.subcategory.category
@school = school @school = school
@academic_years = academic_years @academic_years = academic_years
@position = position @position = position
@number_of_columns = number_of_columns @number_of_columns = number_of_columns
end
def academic_year_for_year_index(year_index)
academic_years[year_index]
end
def score(year_index)
measure.score(school:, academic_year: academic_years[year_index]) || 0
end
def bars
@bars ||= yearly_scores.map.each_with_index do |yearly_score, index|
year = yearly_score.year
Analyze::BarPresenter.new(measure:, academic_year: year,
score: yearly_score.score,
x_position: bar_x(index),
color: bar_color(year))
end
end
def label
%w[All Data]
end
def show_irrelevancy_message?
false
end
def show_insufficient_data_message?
scores = academic_years.map do |year|
measure.score(school:, academic_year: year)
end end
scores.all? do |score| def academic_year_for_year_index(year_index)
!score.meets_teacher_threshold? && !score.meets_student_threshold? && !score.meets_admin_data_threshold? academic_years[year_index]
end end
end
def column_midpoint def score(year_index)
zone_label_width + (grouped_chart_column_width * (position + 1)) - (grouped_chart_column_width / 2) measure.score(school:, academic_year: academic_years[year_index]) || 0
end
def bar_width
min_bar_width(10.5 / data_sources)
end
def min_bar_width(number)
min_width = 2
number < min_width ? min_width : number
end
def message_x
column_midpoint - message_width / 2
end
def message_y
17
end
def message_width
20
end
def message_height
34
end
def column_end_x
zone_label_width + (grouped_chart_column_width * (position + 1))
end
def column_start_x
zone_label_width + (grouped_chart_column_width * position)
end
def grouped_chart_column_width
graph_width / data_sources
end
def bar_label_height
(100 - ((100 - analyze_graph_height) / 2))
end
def data_sources
number_of_columns
end
def basis
"student surveys"
end
def type
:all_data
end
def show_popover?
%i[student teacher].include? type
end
def n_size(year_index)
SurveyItemResponse.where(survey_item: measure.student_survey_items, school:, grade: grades(year_index),
academic_year: academic_years[year_index]).select(:response_id).distinct.count
end
def popover_content(year_index)
"#{n_size(year_index)} #{type.to_s.capitalize}s"
end
def insufficiency_message
["survey response", "rate below 25%"]
end
def sufficient_data?(year_index)
case basis
when "student"
score(year_index).meets_student_threshold
when "teacher"
score(year_index).meets_teacher_threshold
else
true
end end
end
def grades(year_index) def bars
Respondent.by_school_and_year(school:, academic_year: academic_years[year_index]).enrollment_by_grade.keys @bars ||= yearly_scores.map.each_with_index do |yearly_score, index|
end year = yearly_score.year
Analyze::BarPresenter.new(measure:, academic_year: year,
private score: yearly_score.score,
x_position: bar_x(index),
YearlyScore = Struct.new(:year, :score) color: bar_color(year))
def yearly_scores end
yearly_scores = academic_years.each_with_index.map do |year, index|
YearlyScore.new(year, score(index))
end end
yearly_scores.reject do |yearly_score|
yearly_score.score.blank? def label
%w[All Data]
end end
end
def bar_color(year) def show_irrelevancy_message?
@available_academic_years ||= AcademicYear.order(:range).all false
colors[@available_academic_years.find_index(year)] end
end
def bar_x(index) def show_insufficient_data_message?
column_start_x + (index * bar_width * 1.2) + scores = academic_years.map do |year|
((column_end_x - column_start_x) - (yearly_scores.size * bar_width * 1.2)) / 2 measure.score(school:, academic_year: year)
end
scores.all? do |score|
!score.meets_teacher_threshold? && !score.meets_student_threshold? && !score.meets_admin_data_threshold?
end
end
def column_midpoint
zone_label_width + (grouped_chart_column_width * (position + 1)) - (grouped_chart_column_width / 2)
end
def bar_width
min_bar_width(10.5 / data_sources)
end
def min_bar_width(number)
min_width = 2
number < min_width ? min_width : number
end
def message_x
column_midpoint - message_width / 2
end
def message_y
17
end
def message_width
20
end
def message_height
34
end
def column_end_x
zone_label_width + (grouped_chart_column_width * (position + 1))
end
def column_start_x
zone_label_width + (grouped_chart_column_width * position)
end
def grouped_chart_column_width
graph_width / data_sources
end
def bar_label_height
(100 - ((100 - analyze_graph_height) / 2))
end
def data_sources
number_of_columns
end
def basis
"student surveys"
end
def type
:all_data
end
def show_popover?
%i[student teacher].include? type
end
def n_size(year_index)
SurveyItemResponse.where(survey_item: measure.student_survey_items, school:, grade: grades(year_index),
academic_year: academic_years[year_index]).select(:response_id).distinct.count
end
def popover_content(year_index)
"#{n_size(year_index)} #{type.to_s.capitalize}s"
end
def insufficiency_message
["survey response", "rate below 25%"]
end
def sufficient_data?(year_index)
case basis
when "student"
score(year_index).meets_student_threshold
when "teacher"
score(year_index).meets_teacher_threshold
else
true
end
end
def grades(year_index)
Respondent.by_school_and_year(school:, academic_year: academic_years[year_index]).enrollment_by_grade.keys
end
private
YearlyScore = Struct.new(:year, :score)
def yearly_scores
yearly_scores = academic_years.each_with_index.map do |year, index|
YearlyScore.new(year, score(index))
end
yearly_scores.reject do |yearly_score|
yearly_score.score.blank?
end
end
def bar_color(year)
@available_academic_years ||= AcademicYear.order(:range).all
colors[@available_academic_years.find_index(year)]
end
def bar_x(index)
column_start_x + (index * bar_width * 1.2) +
((column_end_x - column_start_x) - (yearly_scores.size * bar_width * 1.2)) / 2
end
end end
end end
end end

View file

@ -1,26 +1,28 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module IncomeColumn module Column
class Disadvantaged < GroupedBarColumnPresenter module IncomeColumn
include Analyze::Graph::Column::IncomeColumn::ScoreForIncome class Disadvantaged < GroupedBarColumnPresenter
include Analyze::Graph::Column::IncomeColumn::IncomeCount include Analyze::Graph::Column::IncomeColumn::ScoreForIncome
def label include Analyze::Graph::Column::IncomeColumn::IncomeCount
%w[Economically Disadvantaged] def label
end %w[Economically Disadvantaged]
end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def income def income
Income.find_by_designation "Economically Disadvantaged - Y" Income.find_by_designation "Economically Disadvantaged - Y"
end
end end
end end
end end

View file

@ -1,15 +1,19 @@
module Analyze # frozen_string_literal: true
module Graph
module Column
module IncomeColumn
module IncomeCount
def type
:student
end
def n_size(year_index) module Dashboard
SurveyItemResponse.where(income:, survey_item: measure.student_survey_items, school:, grade: grades(year_index), module Analyze
academic_year: academic_years[year_index]).select(:response_id).distinct.count module Graph
module Column
module IncomeColumn
module IncomeCount
def type
:student
end
def n_size(year_index)
SurveyItemResponse.where(income:, survey_item: measure.student_survey_items, school:, grade: grades(year_index),
academic_year: academic_years[year_index]).select(:response_id).distinct.count
end
end end
end end
end end

View file

@ -1,26 +1,28 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module IncomeColumn module Column
class NotDisadvantaged < GroupedBarColumnPresenter module IncomeColumn
include Analyze::Graph::Column::IncomeColumn::ScoreForIncome class NotDisadvantaged < GroupedBarColumnPresenter
include Analyze::Graph::Column::IncomeColumn::IncomeCount include Analyze::Graph::Column::IncomeColumn::ScoreForIncome
def label include Analyze::Graph::Column::IncomeColumn::IncomeCount
["Not Economically", "Disadvantaged"] def label
end ["Not Economically", "Disadvantaged"]
end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def income def income
Income.find_by_designation "Economically Disadvantaged - N" Income.find_by_designation "Economically Disadvantaged - N"
end
end end
end end
end end

View file

@ -1,38 +1,42 @@
module Analyze # frozen_string_literal: true
module Graph
module Column
module IncomeColumn
module ScoreForIncome
def score(year_index)
academic_year = academic_years[year_index]
meets_student_threshold = sufficient_student_responses?(academic_year:)
return Score::NIL_SCORE unless meets_student_threshold
averages = SurveyItemResponse.averages_for_income(measure.student_survey_items, school, academic_year, module Dashboard
income) module Analyze
average = bubble_up_averages(averages:).round(2) module Graph
module Column
module IncomeColumn
module ScoreForIncome
def score(year_index)
academic_year = academic_years[year_index]
meets_student_threshold = sufficient_student_responses?(academic_year:)
return Score::NIL_SCORE unless meets_student_threshold
Score.new(average:, averages = SurveyItemResponse.averages_for_income(measure.student_survey_items, school, academic_year,
meets_teacher_threshold: false, income)
meets_student_threshold:, average = bubble_up_averages(averages:).round(2)
meets_admin_data_threshold: false)
end
def bubble_up_averages(averages:) Score.new(average:,
measure.student_scales.map do |scale| meets_teacher_threshold: false,
scale.survey_items.map do |survey_item| meets_student_threshold:,
averages[survey_item] meets_admin_data_threshold: false)
end
def bubble_up_averages(averages:)
measure.student_scales.map do |scale|
scale.survey_items.map do |survey_item|
averages[survey_item]
end.remove_blanks.average
end.remove_blanks.average end.remove_blanks.average
end.remove_blanks.average end
end
def sufficient_student_responses?(academic_year:) def sufficient_student_responses?(academic_year:)
return false unless measure.subcategory.response_rate(school:, academic_year:).meets_student_threshold? return false unless measure.subcategory.response_rate(school:, academic_year:).meets_student_threshold?
yearly_counts = SurveyItemResponse.where(school:, academic_year:, yearly_counts = SurveyItemResponse.where(school:, academic_year:,
income:, survey_item: measure.student_survey_items).group(:income).select(:response_id).distinct(:response_id).count income:, survey_item: measure.student_survey_items).group(:income).select(:response_id).distinct(:response_id).count
yearly_counts.any? do |count| yearly_counts.any? do |count|
count[1] >= 10 count[1] >= 10
end
end end
end end
end end

View file

@ -1,26 +1,28 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module IncomeColumn module Column
class Unknown < GroupedBarColumnPresenter module IncomeColumn
include Analyze::Graph::Column::IncomeColumn::ScoreForIncome class Unknown < GroupedBarColumnPresenter
include Analyze::Graph::Column::IncomeColumn::IncomeCount include Analyze::Graph::Column::IncomeColumn::ScoreForIncome
def label include Analyze::Graph::Column::IncomeColumn::IncomeCount
["Unknown"] def label
end ["Unknown"]
end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def income def income
Income.find_by_designation "Unknown" Income.find_by_designation "Unknown"
end
end end
end end
end end

View file

@ -1,26 +1,28 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module RaceColumn module Column
class AmericanIndian < GroupedBarColumnPresenter module RaceColumn
include Analyze::Graph::Column::ScoreForRace class AmericanIndian < GroupedBarColumnPresenter
include Analyze::Graph::Column::RaceColumn::RaceCount include Analyze::Graph::Column::ScoreForRace
def label include Analyze::Graph::Column::RaceColumn::RaceCount
%w[American Indian] def label
end %w[American Indian]
end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def race def race
Race.find_by_qualtrics_code 1 Race.find_by_qualtrics_code 1
end
end end
end end
end end

View file

@ -1,26 +1,28 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module RaceColumn module Column
class Asian < GroupedBarColumnPresenter module RaceColumn
include Analyze::Graph::Column::ScoreForRace class Asian < GroupedBarColumnPresenter
include Analyze::Graph::Column::RaceColumn::RaceCount include Analyze::Graph::Column::ScoreForRace
def label include Analyze::Graph::Column::RaceColumn::RaceCount
%w[Asian] def label
end %w[Asian]
end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def race def race
Race.find_by_qualtrics_code 2 Race.find_by_qualtrics_code 2
end
end end
end end
end end

View file

@ -1,26 +1,28 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module RaceColumn module Column
class Black < GroupedBarColumnPresenter module RaceColumn
include Analyze::Graph::Column::ScoreForRace class Black < GroupedBarColumnPresenter
include Analyze::Graph::Column::RaceColumn::RaceCount include Analyze::Graph::Column::ScoreForRace
def label include Analyze::Graph::Column::RaceColumn::RaceCount
%w[Black] def label
end %w[Black]
end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def race def race
Race.find_by_qualtrics_code 3 Race.find_by_qualtrics_code 3
end
end end
end end
end end

View file

@ -1,26 +1,28 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module RaceColumn module Column
class Hispanic < GroupedBarColumnPresenter module RaceColumn
include Analyze::Graph::Column::ScoreForRace class Hispanic < GroupedBarColumnPresenter
include Analyze::Graph::Column::RaceColumn::RaceCount include Analyze::Graph::Column::ScoreForRace
def label include Analyze::Graph::Column::RaceColumn::RaceCount
%w[Hispanic] def label
end %w[Hispanic]
end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def race def race
Race.find_by_qualtrics_code 4 Race.find_by_qualtrics_code 4
end
end end
end end
end end

View file

@ -1,27 +1,29 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module RaceColumn module Column
class MiddleEastern < GroupedBarColumnPresenter module RaceColumn
include Analyze::Graph::Column::ScoreForRace class MiddleEastern < GroupedBarColumnPresenter
include Analyze::Graph::Column::RaceColumn::RaceCount include Analyze::Graph::Column::ScoreForRace
include Analyze::Graph::Column::RaceColumn::RaceCount
def label def label
%w[Middle Eastern] %w[Middle Eastern]
end end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def race def race
Race.find_by_qualtrics_code 8 Race.find_by_qualtrics_code 8
end
end end
end end
end end

View file

@ -1,26 +1,28 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module RaceColumn module Column
class Multiracial < GroupedBarColumnPresenter module RaceColumn
include Analyze::Graph::Column::ScoreForRace class Multiracial < GroupedBarColumnPresenter
include Analyze::Graph::Column::RaceColumn::RaceCount include Analyze::Graph::Column::ScoreForRace
def label include Analyze::Graph::Column::RaceColumn::RaceCount
%w[Multiracial] def label
end %w[Multiracial]
end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def race def race
Race.find_by_qualtrics_code 100 Race.find_by_qualtrics_code 100
end
end end
end end
end end

View file

@ -1,17 +1,21 @@
module Analyze # frozen_string_literal: true
module Graph
module Column
module RaceColumn
module RaceCount
def type
:student
end
def n_size(year_index) module Dashboard
SurveyItemResponse.joins("JOIN student_races on survey_item_responses.student_id = student_races.student_id JOIN students on students.id = student_races.student_id").where( module Analyze
school:, academic_year: academic_years[year_index], module Graph
survey_item: measure.student_survey_items module Column
).where("student_races.race_id": race.id).select(:response_id).distinct.count module RaceColumn
module RaceCount
def type
:student
end
def n_size(year_index)
SurveyItemResponse.joins("JOIN student_races on survey_item_responses.student_id = student_races.student_id JOIN students on students.id = student_races.student_id").where(
school:, academic_year: academic_years[year_index],
survey_item: measure.student_survey_items
).where("student_races.race_id": race.id).select(:response_id).distinct.count
end
end end
end end
end end

View file

@ -1,26 +1,28 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module RaceColumn module Column
class Unknown < GroupedBarColumnPresenter module RaceColumn
include Analyze::Graph::Column::ScoreForRace class Unknown < GroupedBarColumnPresenter
include Analyze::Graph::Column::RaceColumn::RaceCount include Analyze::Graph::Column::ScoreForRace
def label include Analyze::Graph::Column::RaceColumn::RaceCount
%w[Not Listed] def label
end %w[Not Listed]
end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def race def race
Race.find_by_qualtrics_code 99 Race.find_by_qualtrics_code 99
end
end end
end end
end end

View file

@ -1,26 +1,28 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module RaceColumn module Column
class White < GroupedBarColumnPresenter module RaceColumn
include Analyze::Graph::Column::ScoreForRace class White < GroupedBarColumnPresenter
include Analyze::Graph::Column::RaceColumn::RaceCount include Analyze::Graph::Column::ScoreForRace
def label include Analyze::Graph::Column::RaceColumn::RaceCount
%w[White] def label
end %w[White]
end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def race def race
Race.find_by_qualtrics_code 5 Race.find_by_qualtrics_code 5
end
end end
end end
end end

View file

@ -1,38 +1,42 @@
module Analyze # frozen_string_literal: true
module Graph
module Column
module ScoreForRace
def score(year_index)
academic_year = academic_years[year_index]
meets_student_threshold = sufficient_student_responses?(academic_year:)
return Score::NIL_SCORE unless meets_student_threshold
survey_items = measure.student_survey_items module Dashboard
module Analyze
module Graph
module Column
module ScoreForRace
def score(year_index)
academic_year = academic_years[year_index]
meets_student_threshold = sufficient_student_responses?(academic_year:)
return Score::NIL_SCORE unless meets_student_threshold
averages = SurveyItemResponse.averages_for_race(school, academic_year, race) survey_items = measure.student_survey_items
average = bubble_up_averages(averages:).round(2)
Score.new(average:, averages = SurveyItemResponse.averages_for_race(school, academic_year, race)
meets_teacher_threshold: false, average = bubble_up_averages(averages:).round(2)
meets_student_threshold:,
meets_admin_data_threshold: false)
end
def bubble_up_averages(averages:) Score.new(average:,
measure.student_scales.map do |scale| meets_teacher_threshold: false,
scale.survey_items.map do |survey_item| meets_student_threshold:,
averages[survey_item.id] meets_admin_data_threshold: false)
end
def bubble_up_averages(averages:)
measure.student_scales.map do |scale|
scale.survey_items.map do |survey_item|
averages[survey_item.id]
end.remove_blanks.average
end.remove_blanks.average end.remove_blanks.average
end.remove_blanks.average end
end
def sufficient_student_responses?(academic_year:) def sufficient_student_responses?(academic_year:)
return false unless measure.subcategory.response_rate(school:, academic_year:).meets_student_threshold? return false unless measure.subcategory.response_rate(school:, academic_year:).meets_student_threshold?
number_of_students_for_a_racial_group = SurveyItemResponse.joins("JOIN student_races on dashboard_survey_item_responses.student_id = student_races.student_id JOIN students on students.id = student_races.student_id").where( number_of_students_for_a_racial_group = SurveyItemResponse.joins("JOIN student_races on dashboard_survey_item_responses.student_id = student_races.student_id JOIN students on students.id = student_races.student_id").where(
school:, academic_year: school:, academic_year:
).where("student_races.race_id": race.id).distinct.pluck(:student_id).count ).where("student_races.race_id": race.id).distinct.pluck(:student_id).count
number_of_students_for_a_racial_group >= 10 number_of_students_for_a_racial_group >= 10
end
end end
end end
end end

View file

@ -1,31 +1,33 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module SpedColumn module Column
class NotSped < GroupedBarColumnPresenter module SpedColumn
include Analyze::Graph::Column::SpedColumn::ScoreForSped class NotSped < GroupedBarColumnPresenter
include Analyze::Graph::Column::SpedColumn::SpedCount include Analyze::Graph::Column::SpedColumn::ScoreForSped
include Analyze::Graph::Column::SpedColumn::SpedCount
def label def label
["Not Special", "Education"] ["Not Special", "Education"]
end end
def basis def basis
"student" "student"
end end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def sped def sped
::Sped.find_by_slug "not-special-education" ::Sped.find_by_slug "not-special-education"
end
end end
end end
end end

View file

@ -1,38 +1,42 @@
module Analyze # frozen_string_literal: true
module Graph
module Column
module SpedColumn
module ScoreForSped
def score(year_index)
academic_year = academic_years[year_index]
meets_student_threshold = sufficient_student_responses?(academic_year:)
return Score::NIL_SCORE unless meets_student_threshold
averages = SurveyItemResponse.averages_for_sped(measure.student_survey_items, school, academic_year, module Dashboard
sped) module Analyze
average = bubble_up_averages(averages:).round(2) module Graph
module Column
module SpedColumn
module ScoreForSped
def score(year_index)
academic_year = academic_years[year_index]
meets_student_threshold = sufficient_student_responses?(academic_year:)
return Score::NIL_SCORE unless meets_student_threshold
Score.new(average:, averages = SurveyItemResponse.averages_for_sped(measure.student_survey_items, school, academic_year,
meets_teacher_threshold: false, sped)
meets_student_threshold:, average = bubble_up_averages(averages:).round(2)
meets_admin_data_threshold: false)
end
def bubble_up_averages(averages:) Score.new(average:,
measure.student_scales.map do |scale| meets_teacher_threshold: false,
scale.survey_items.map do |survey_item| meets_student_threshold:,
averages[survey_item] meets_admin_data_threshold: false)
end
def bubble_up_averages(averages:)
measure.student_scales.map do |scale|
scale.survey_items.map do |survey_item|
averages[survey_item]
end.remove_blanks.average
end.remove_blanks.average end.remove_blanks.average
end.remove_blanks.average end
end
def sufficient_student_responses?(academic_year:) def sufficient_student_responses?(academic_year:)
return false unless measure.subcategory.response_rate(school:, academic_year:).meets_student_threshold? return false unless measure.subcategory.response_rate(school:, academic_year:).meets_student_threshold?
yearly_counts = SurveyItemResponse.where(school:, academic_year:, yearly_counts = SurveyItemResponse.where(school:, academic_year:,
sped:, survey_item: measure.student_survey_items).group(:sped).select(:response_id).distinct(:response_id).count sped:, survey_item: measure.student_survey_items).group(:sped).select(:response_id).distinct(:response_id).count
yearly_counts.any? do |count| yearly_counts.any? do |count|
count[1] >= 10 count[1] >= 10
end
end end
end end
end end

View file

@ -1,31 +1,33 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module SpedColumn module Column
class Sped < GroupedBarColumnPresenter module SpedColumn
include Analyze::Graph::Column::SpedColumn::ScoreForSped class Sped < GroupedBarColumnPresenter
include Analyze::Graph::Column::SpedColumn::SpedCount include Analyze::Graph::Column::SpedColumn::ScoreForSped
include Analyze::Graph::Column::SpedColumn::SpedCount
def label def label
%w[Special Education] %w[Special Education]
end end
def basis def basis
"student" "student"
end end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def sped def sped
::Sped.find_by_slug "special-education" ::Sped.find_by_slug "special-education"
end
end end
end end
end end

View file

@ -1,15 +1,19 @@
module Analyze # frozen_string_literal: true
module Graph
module Column
module SpedColumn
module SpedCount
def type
:student
end
def n_size(year_index) module Dashboard
SurveyItemResponse.where(sped:, survey_item: measure.student_survey_items, school:, grade: grades(year_index), module Analyze
academic_year: academic_years[year_index]).select(:response_id).distinct.count module Graph
module Column
module SpedColumn
module SpedCount
def type
:student
end
def n_size(year_index)
SurveyItemResponse.where(sped:, survey_item: measure.student_survey_items, school:, grade: grades(year_index),
academic_year: academic_years[year_index]).select(:response_id).distinct.count
end
end end
end end
end end

View file

@ -1,31 +1,33 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
module Column module Graph
module SpedColumn module Column
class Unknown < GroupedBarColumnPresenter module SpedColumn
include Analyze::Graph::Column::SpedColumn::ScoreForSped class Unknown < GroupedBarColumnPresenter
include Analyze::Graph::Column::SpedColumn::SpedCount include Analyze::Graph::Column::SpedColumn::ScoreForSped
include Analyze::Graph::Column::SpedColumn::SpedCount
def label def label
%w[Unknown] %w[Unknown]
end end
def basis def basis
"student" "student"
end end
def show_irrelevancy_message? def show_irrelevancy_message?
false false
end end
def show_insufficient_data_message? def show_insufficient_data_message?
false false
end end
def sped def sped
::Sped.find_by_slug "unknown" ::Sped.find_by_slug "unknown"
end
end end
end end
end end

View file

@ -1,19 +1,21 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
class StudentsAndTeachers module Graph
include Analyze::Graph::Column class StudentsAndTeachers
def to_s include Analyze::Graph::Column
'Students & Teachers' def to_s
end "Students & Teachers"
end
def slug def slug
'students-and-teachers' "students-and-teachers"
end end
def columns def columns
[AllStudent, AllTeacher, AllSurveyData] [AllStudent, AllTeacher, AllSurveyData]
end
end end
end end
end end

View file

@ -1,44 +1,46 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
class StudentsByEll module Graph
include Analyze::Graph::Column::EllColumn class StudentsByEll
attr_reader :ells include Analyze::Graph::Column::EllColumn
attr_reader :ells
def initialize(ells:) def initialize(ells:)
@ells = ells @ells = ells
end
def to_s
"Students by Ell"
end
def slug
"students-by-ell"
end
def columns
[].tap do |array|
ells.each do |ell|
array << column_for_ell_code(code: ell.slug)
end
array.sort_by!(&:to_s)
array << Analyze::Graph::Column::AllStudent
end end
def to_s
"Students by Ell"
end
def slug
"students-by-ell"
end
def columns
[].tap do |array|
ells.each do |ell|
array << column_for_ell_code(code: ell.slug)
end
array.sort_by!(&:to_s)
array << Analyze::Graph::Column::AllStudent
end
end
private
def column_for_ell_code(code:)
CFR[code]
end
CFR = {
"ell" => Analyze::Graph::Column::EllColumn::Ell,
"not-ell" => Analyze::Graph::Column::EllColumn::NotEll,
"unknown" => Analyze::Graph::Column::EllColumn::Unknown
}.freeze
end end
private
def column_for_ell_code(code:)
CFR[code]
end
CFR = {
"ell" => Analyze::Graph::Column::EllColumn::Ell,
"not-ell" => Analyze::Graph::Column::EllColumn::NotEll,
"unknown" => Analyze::Graph::Column::EllColumn::Unknown
}.freeze
end end
end end
end end

View file

@ -1,45 +1,47 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
class StudentsByGender module Graph
include Analyze::Graph::Column::GenderColumn class StudentsByGender
attr_reader :genders include Analyze::Graph::Column::GenderColumn
attr_reader :genders
def initialize(genders:) def initialize(genders:)
@genders = genders @genders = genders
end
def to_s
"Students by Gender"
end
def slug
"students-by-gender"
end
def columns
[].tap do |array|
genders.each do |gender|
array << column_for_gender_code(code: gender.qualtrics_code)
end
array.sort_by!(&:to_s)
array << Analyze::Graph::Column::AllStudent
end end
def to_s
"Students by Gender"
end
def slug
"students-by-gender"
end
def columns
[].tap do |array|
genders.each do |gender|
array << column_for_gender_code(code: gender.qualtrics_code)
end
array.sort_by!(&:to_s)
array << Analyze::Graph::Column::AllStudent
end
end
private
def column_for_gender_code(code:)
CFR[code]
end
CFR = {
1 => Analyze::Graph::Column::GenderColumn::Female,
2 => Analyze::Graph::Column::GenderColumn::Male,
4 => Analyze::Graph::Column::GenderColumn::NonBinary,
99 => Analyze::Graph::Column::GenderColumn::Unknown
}.freeze
end end
private
def column_for_gender_code(code:)
CFR[code]
end
CFR = {
1 => Analyze::Graph::Column::GenderColumn::Female,
2 => Analyze::Graph::Column::GenderColumn::Male,
4 => Analyze::Graph::Column::GenderColumn::NonBinary,
99 => Analyze::Graph::Column::GenderColumn::Unknown
}.freeze
end end
end end
end end

View file

@ -1,53 +1,55 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
class StudentsByGrade module Graph
include Analyze::Graph::Column::Grade class StudentsByGrade
attr_reader :grades include Analyze::Graph::Column::Grade
attr_reader :grades
def initialize(grades:) def initialize(grades:)
@grades = grades @grades = grades
end
def to_s
"Students by Grade"
end
def slug
"students-by-grade"
end
def columns
[].tap do |array|
grades.each do |grade|
array << column_for_grade_code(code: grade)
end
array << Analyze::Graph::Column::AllStudent
end end
def to_s
"Students by Grade"
end
def slug
"students-by-grade"
end
def columns
[].tap do |array|
grades.each do |grade|
array << column_for_grade_code(code: grade)
end
array << Analyze::Graph::Column::AllStudent
end
end
private
def column_for_grade_code(code:)
CFR[code]
end
CFR = {
0 => Zero,
1 => One,
2 => Two,
3 => Three,
4 => Four,
5 => Five,
6 => Six,
7 => Seven,
8 => Eight,
9 => Nine,
10 => Ten,
11 => Eleven,
12 => Twelve
}.freeze
end end
private
def column_for_grade_code(code:)
CFR[code]
end
CFR = {
0 => Zero,
1 => One,
2 => Two,
3 => Three,
4 => Four,
5 => Five,
6 => Six,
7 => Seven,
8 => Eight,
9 => Nine,
10 => Ten,
11 => Eleven,
12 => Twelve
}.freeze
end end
end end
end end

View file

@ -1,42 +1,44 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
class StudentsByIncome module Graph
attr_reader :incomes class StudentsByIncome
attr_reader :incomes
def initialize(incomes:) def initialize(incomes:)
@incomes = incomes @incomes = incomes
end
def to_s
"Students by income"
end
def slug
"students-by-income"
end
def columns
[].tap do |array|
incomes.each do |income|
array << column_for_income_code(code: income.slug)
end
array << Analyze::Graph::Column::AllStudent
end end
def to_s
"Students by income"
end
def slug
"students-by-income"
end
def columns
[].tap do |array|
incomes.each do |income|
array << column_for_income_code(code: income.slug)
end
array << Analyze::Graph::Column::AllStudent
end
end
private
def column_for_income_code(code:)
CFR[code.to_s]
end
CFR = {
"economically-disadvantaged-y" => Analyze::Graph::Column::IncomeColumn::Disadvantaged,
"economically-disadvantaged-n" => Analyze::Graph::Column::IncomeColumn::NotDisadvantaged,
"unknown" => Analyze::Graph::Column::IncomeColumn::Unknown
}.freeze
end end
private
def column_for_income_code(code:)
CFR[code.to_s]
end
CFR = {
"economically-disadvantaged-y" => Analyze::Graph::Column::IncomeColumn::Disadvantaged,
"economically-disadvantaged-n" => Analyze::Graph::Column::IncomeColumn::NotDisadvantaged,
"unknown" => Analyze::Graph::Column::IncomeColumn::Unknown
}.freeze
end end
end end
end end

View file

@ -1,47 +1,49 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
class StudentsByRace module Graph
attr_reader :races class StudentsByRace
attr_reader :races
def initialize(races:) def initialize(races:)
@races = races @races = races
end
def to_s
"Students by Race"
end
def slug
"students-by-race"
end
def columns
[].tap do |array|
races.each do |race|
array << column_for_race_code(code: race.qualtrics_code)
end
array << Analyze::Graph::Column::AllStudent
end end
def to_s
"Students by Race"
end
def slug
"students-by-race"
end
def columns
[].tap do |array|
races.each do |race|
array << column_for_race_code(code: race.qualtrics_code)
end
array << Analyze::Graph::Column::AllStudent
end
end
private
def column_for_race_code(code:)
CFR[code.to_s]
end
CFR = {
"1" => Analyze::Graph::Column::RaceColumn::AmericanIndian,
"2" => Analyze::Graph::Column::RaceColumn::Asian,
"3" => Analyze::Graph::Column::RaceColumn::Black,
"4" => Analyze::Graph::Column::RaceColumn::Hispanic,
"5" => Analyze::Graph::Column::RaceColumn::White,
"8" => Analyze::Graph::Column::RaceColumn::MiddleEastern,
"99" => Analyze::Graph::Column::RaceColumn::Unknown,
"100" => Analyze::Graph::Column::RaceColumn::Multiracial
}.freeze
end end
private
def column_for_race_code(code:)
CFR[code.to_s]
end
CFR = {
"1" => Analyze::Graph::Column::RaceColumn::AmericanIndian,
"2" => Analyze::Graph::Column::RaceColumn::Asian,
"3" => Analyze::Graph::Column::RaceColumn::Black,
"4" => Analyze::Graph::Column::RaceColumn::Hispanic,
"5" => Analyze::Graph::Column::RaceColumn::White,
"8" => Analyze::Graph::Column::RaceColumn::MiddleEastern,
"99" => Analyze::Graph::Column::RaceColumn::Unknown,
"100" => Analyze::Graph::Column::RaceColumn::Multiracial
}.freeze
end end
end end
end end

View file

@ -1,43 +1,45 @@
# frozen_string_literal: true # frozen_string_literal: true
module Analyze module Dashboard
module Graph module Analyze
class StudentsBySped module Graph
include Analyze::Graph::Column::SpedColumn class StudentsBySped
attr_reader :speds include Analyze::Graph::Column::SpedColumn
attr_reader :speds
def initialize(speds:) def initialize(speds:)
@speds = speds @speds = speds
end
def to_s
"Students by SpEd"
end
def slug
"students-by-sped"
end
def columns
[].tap do |array|
speds.each do |sped|
array << column_for_sped_code(code: sped.slug)
end
array << Analyze::Graph::Column::AllStudent
end end
def to_s
"Students by SpEd"
end
def slug
"students-by-sped"
end
def columns
[].tap do |array|
speds.each do |sped|
array << column_for_sped_code(code: sped.slug)
end
array << Analyze::Graph::Column::AllStudent
end
end
private
def column_for_sped_code(code:)
CFR[code]
end
CFR = {
"special-education" => Analyze::Graph::Column::SpedColumn::Sped,
"not-special-education" => Analyze::Graph::Column::SpedColumn::NotSped,
"unknown" => Analyze::Graph::Column::SpedColumn::Unknown
}.freeze
end end
private
def column_for_sped_code(code:)
CFR[code]
end
CFR = {
"special-education" => Analyze::Graph::Column::SpedColumn::Sped,
"not-special-education" => Analyze::Graph::Column::SpedColumn::NotSped,
"unknown" => Analyze::Graph::Column::SpedColumn::Unknown
}.freeze
end end
end end
end end

View file

@ -1,12 +1,16 @@
module Analyze # frozen_string_literal: true
module Group
class Ell
def name
"ELL"
end
def slug module Dashboard
"ell" module Analyze
module Group
class Ell
def name
"ELL"
end
def slug
"ell"
end
end end
end end
end end

View file

@ -1,12 +1,16 @@
module Analyze # frozen_string_literal: true
module Group
class Gender
def name
'Gender'
end
def slug module Dashboard
'gender' module Analyze
module Group
class Gender
def name
"Gender"
end
def slug
"gender"
end
end end
end end
end end

View file

@ -1,12 +1,16 @@
module Analyze # frozen_string_literal: true
module Group
class Grade
def name
'Grade'
end
def slug module Dashboard
'grade' module Analyze
module Group
class Grade
def name
"Grade"
end
def slug
"grade"
end
end end
end end
end end

View file

@ -1,12 +1,16 @@
module Analyze # frozen_string_literal: true
module Group
class Income
def name
'Income'
end
def slug module Dashboard
'income' module Analyze
module Group
class Income
def name
"Income"
end
def slug
"income"
end
end end
end end
end end

View file

@ -1,12 +1,16 @@
module Analyze # frozen_string_literal: true
module Group
class Race
def name
'Race'
end
def slug module Dashboard
'race' module Analyze
module Group
class Race
def name
"Race"
end
def slug
"race"
end
end end
end end
end end

View file

@ -1,12 +1,16 @@
module Analyze # frozen_string_literal: true
module Group
class Sped
def name
"Special Education"
end
def slug module Dashboard
"sped" module Analyze
module Group
class Sped
def name
"Special Education"
end
def slug
"sped"
end
end end
end end
end end

View file

@ -1,200 +1,206 @@
module Analyze module Dashboard
class Presenter module Analyze
attr_reader :params, :school, :academic_year class Presenter
attr_reader :params, :school, :academic_year
def initialize(params:, school:, academic_year:) def initialize(params:, school:, academic_year:)
@params = params @params = params
@school = school @school = school
@academic_year = academic_year @academic_year = academic_year
end
def category
@category ||= Category.find_by_category_id(params[:category]) || Category.order(:category_id).first
end
def categories
@categories = Category.all.order(:category_id)
end
def subcategory
@subcategory ||= Subcategory.find_by_subcategory_id(params[:subcategory]) || subcategories.first
end
def subcategories
@subcategories = category.subcategories.order(:subcategory_id)
end
def measures
@measures = subcategory.measures.order(:measure_id).includes(%i[admin_data_items subcategory])
end
def academic_years
@academic_years = AcademicYear.order(:range).all
end
def selected_academic_years
@selected_academic_years ||= begin
year_params = params[:academic_years]
return [] unless year_params
year_params.split(",").map { |year| AcademicYear.find_by_range(year) }.compact
end end
end
def races def category
@races ||= Race.all.order(designation: :ASC) @category ||= Category.find_by_category_id(params[:category]) || Category.order(:category_id).first
end
def selected_races
@selected_races ||= begin
race_params = params[:races]
return races unless race_params
race_params.split(",").map { |race| Race.find_by_slug race }.compact
end end
end
def ells def categories
@ells ||= Ell.all.order(slug: :ASC) @categories = Category.all.order(:category_id)
end
def selected_ells
@selected_ells ||= begin
ell_params = params[:ells]
return ells unless ell_params
ell_params.split(",").map { |ell| Ell.find_by_slug ell }.compact
end end
end
def speds def subcategory
@speds ||= Sped.all.order(id: :ASC) @subcategory ||= Subcategory.find_by_subcategory_id(params[:subcategory]) || subcategories.first
end
def selected_speds
@selected_speds ||= begin
sped_params = params[:speds]
return speds unless sped_params
sped_params.split(",").map { |sped| Sped.find_by_slug sped }.compact
end end
end
def graphs def subcategories
@graphs ||= [Analyze::Graph::AllData.new, @subcategories = category.subcategories.order(:subcategory_id)
Analyze::Graph::StudentsAndTeachers.new,
Analyze::Graph::StudentsByRace.new(races: selected_races),
Analyze::Graph::StudentsByGrade.new(grades: selected_grades),
Analyze::Graph::StudentsByGender.new(genders: selected_genders),
Analyze::Graph::StudentsByIncome.new(incomes: selected_incomes),
Analyze::Graph::StudentsByEll.new(ells: selected_ells),
Analyze::Graph::StudentsBySped.new(speds: selected_speds)]
end
def graph
@graph ||= graphs.reduce(graphs.first) do |acc, graph|
graph.slug == params[:graph] ? graph : acc
end end
end
def selected_grades def measures
@selected_grades ||= begin @measures = subcategory.measures.order(:measure_id).includes(%i[admin_data_items subcategory])
grade_params = params[:grades]
return grades unless grade_params
grade_params.split(",").map(&:to_i)
end end
end
def selected_genders def academic_years
@selected_genders ||= begin @academic_years = AcademicYear.order(:range).all
gender_params = params[:genders]
return genders unless gender_params
gender_params.split(",").sort.map { |gender| Gender.find_by_designation(gender) }.compact
end end
end
def genders def selected_academic_years
@genders ||= Gender.all.order(designation: :ASC) @selected_academic_years ||= begin
end year_params = params[:academic_years]
return [] unless year_params
def groups year_params.split(",").map { |year| AcademicYear.find_by_range(year) }.compact
@groups = [Analyze::Group::Ell.new, Analyze::Group::Gender.new, Analyze::Group::Grade.new, Analyze::Group::Income.new, end
Analyze::Group::Race.new, Analyze::Group::Sped.new]
end
def group
@group ||= groups.reduce(groups.first) do |acc, group|
group.slug == params[:group] ? group : acc
end end
end
def slice def races
@slice ||= slices.reduce(slices.first) do |acc, slice| @races ||= Race.all.order(designation: :ASC)
slice.slug == params[:slice] ? slice : acc
end end
end
def slices def selected_races
source.slices @selected_races ||= begin
end race_params = params[:races]
return races unless race_params
def source race_params.split(",").map { |race| Race.find_by_slug race }.compact
@source ||= sources.reduce(sources.first) do |acc, source| end
source.slug == params[:source] ? source : acc
end end
end
def sources def ells
all_data_slices = [Analyze::Slice::AllData.new] @ells ||= Ell.all.order(slug: :ASC)
all_data_source = Analyze::Source::AllData.new(slices: all_data_slices)
students_and_teachers = Analyze::Slice::StudentsAndTeachers.new
students_by_group = Analyze::Slice::StudentsByGroup.new(races:, grades:)
survey_data_slices = [students_and_teachers, students_by_group]
survey_data_source = Analyze::Source::SurveyData.new(slices: survey_data_slices)
@sources = [all_data_source, survey_data_source]
end
def grades
@grades ||= SurveyItemResponse.where(school:, academic_year:)
.where.not(grade: nil)
.group(:grade)
.select(:response_id)
.distinct(:response_id)
.count.reject do |_key, value|
value < 10
end.keys
end
def incomes
@incomes ||= Income.all
end
def selected_incomes
@selected_incomes ||= begin
income_params = params[:incomes]
return incomes unless income_params
income_params.split(",").map { |income| Income.find_by_slug(income) }.compact
end end
end
def cache_objects def selected_ells
[subcategory, @selected_ells ||= begin
selected_academic_years, ell_params = params[:ells]
graph, return ells unless ell_params
selected_races,
selected_grades, ell_params.split(",").map { |ell| Ell.find_by_slug ell }.compact
grades, end
selected_genders, end
genders,
selected_ells, def speds
ells, @speds ||= Sped.all.order(id: :ASC)
selected_speds, end
speds]
def selected_speds
@selected_speds ||= begin
sped_params = params[:speds]
return speds unless sped_params
sped_params.split(",").map { |sped| Sped.find_by_slug sped }.compact
end
end
def graphs
@graphs ||= [Analyze::Graph::AllData.new,
Analyze::Graph::StudentsAndTeachers.new,
Analyze::Graph::StudentsByRace.new(races: selected_races),
Analyze::Graph::StudentsByGrade.new(grades: selected_grades),
Analyze::Graph::StudentsByGender.new(genders: selected_genders),
Analyze::Graph::StudentsByIncome.new(incomes: selected_incomes),
Analyze::Graph::StudentsByEll.new(ells: selected_ells),
Analyze::Graph::StudentsBySped.new(speds: selected_speds)]
end
def graph
@graph ||= graphs.reduce(graphs.first) do |acc, graph|
graph.slug == params[:graph] ? graph : acc
end
end
def selected_grades
@selected_grades ||= begin
grade_params = params[:grades]
return grades unless grade_params
grade_params.split(",").map(&:to_i)
end
end
def selected_genders
@selected_genders ||= begin
gender_params = params[:genders]
return genders unless gender_params
gender_params.split(",").sort.map { |gender| Gender.find_by_designation(gender) }.compact
end
end
def genders
@genders ||= Gender.all.order(designation: :ASC)
end
def groups
@groups = [Analyze::Group::Ell.new,
Analyze::Group::Gender.new,
Analyze::Group::Grade.new,
Analyze::Group::Income.new,
Analyze::Group::Race.new,
Analyze::Group::Sped.new]
end
def group
@group ||= groups.reduce(groups.first) do |acc, group|
group.slug == params[:group] ? group : acc
end
end
def slice
@slice ||= slices.reduce(slices.first) do |acc, slice|
slice.slug == params[:slice] ? slice : acc
end
end
def slices
source.slices
end
def source
@source ||= sources.reduce(sources.first) do |acc, source|
source.slug == params[:source] ? source : acc
end
end
def sources
all_data_slices = [Analyze::Slice::AllData.new]
all_data_source = Analyze::Source::AllData.new(slices: all_data_slices)
students_and_teachers = Analyze::Slice::StudentsAndTeachers.new
students_by_group = Analyze::Slice::StudentsByGroup.new(races:, grades:)
survey_data_slices = [students_and_teachers, students_by_group]
survey_data_source = Analyze::Source::SurveyData.new(slices: survey_data_slices)
@sources = [all_data_source, survey_data_source]
end
def grades
@grades ||= SurveyItemResponse.where(school:, academic_year:)
.where.not(grade: nil)
.group(:grade)
.select(:response_id)
.distinct(:response_id)
.count.reject do |_key, value|
value < 10
end.keys
end
def incomes
@incomes ||= Income.all
end
def selected_incomes
@selected_incomes ||= begin
income_params = params[:incomes]
return incomes unless income_params
income_params.split(",").map { |income| Income.find_by_slug(income) }.compact
end
end
def cache_objects
[subcategory,
selected_academic_years,
graph,
selected_races,
selected_grades,
grades,
selected_genders,
genders,
selected_ells,
ells,
selected_speds,
speds]
end
end end
end end
end end

View file

@ -1,16 +1,20 @@
module Analyze # frozen_string_literal: true
module Slice
class AllData
def to_s
'All Data'
end
def slug module Dashboard
'all-data' module Analyze
end module Slice
class AllData
def to_s
"All Data"
end
def graphs def slug
[Analyze::Graph::AllData.new] "all-data"
end
def graphs
[Analyze::Graph::AllData.new]
end
end end
end end
end end

View file

@ -1,16 +1,20 @@
module Analyze # frozen_string_literal: true
module Slice
class StudentsAndTeachers
def to_s
'Students & Teachers'
end
def slug module Dashboard
'students-and-teachers' module Analyze
end module Slice
class StudentsAndTeachers
def to_s
"Students & Teachers"
end
def graphs def slug
[Analyze::Graph::StudentsAndTeachers.new] "students-and-teachers"
end
def graphs
[Analyze::Graph::StudentsAndTeachers.new]
end
end end
end end
end end

View file

@ -1,23 +1,28 @@
module Analyze # frozen_string_literal: true
module Slice
class StudentsByGroup
attr_reader :races, :grades
def initialize(races:, grades:) module Dashboard
@races = races module Analyze
@grades = grades module Slice
end class StudentsByGroup
attr_reader :races, :grades
def to_s def initialize(races:, grades:)
'Students by Group' @races = races
end @grades = grades
end
def slug def to_s
'students-by-group' "Students by Group"
end end
def graphs def slug
[Analyze::Graph::StudentsByRace.new(races:), Analyze::Graph::StudentsByGrade.new(grades:)] "students-by-group"
end
def graphs
[Analyze::Graph::StudentsByRace.new(races:),
Analyze::Graph::StudentsByGrade.new(grades:)]
end
end end
end end
end end

View file

@ -1,20 +1,24 @@
module Analyze # frozen_string_literal: true
module Source
class AllData
attr_reader :slices
include Analyze::Slice module Dashboard
module Analyze
module Source
class AllData
attr_reader :slices
def initialize(slices:) include Analyze::Slice
@slices = slices
end
def to_s def initialize(slices:)
'All Data' @slices = slices
end end
def slug def to_s
'all-data' "All Data"
end
def slug
"all-data"
end
end end
end end
end end

View file

@ -1,20 +1,24 @@
module Analyze # frozen_string_literal: true
module Source
class SurveyData
attr_reader :slices
include Analyze::Slice module Dashboard
module Analyze
module Source
class SurveyData
attr_reader :slices
def initialize(slices:) include Analyze::Slice
@slices = slices
end
def to_s def initialize(slices:)
'Survey Data Only' @slices = slices
end end
def slug def to_s
'survey-data-only' "Survey Data Only"
end
def slug
"survey-data-only"
end
end end
end end
end end

View file

@ -0,0 +1,17 @@
<div class="d-flex align-items-center mx-5">
<input
id="<%= id %>"
class="m-3 <%= name %>-checkbox form-check-input"
type="checkbox"
name="<%= name %>-checkbox"
value="<%= base_url %>"
data-action="click->analyze#refresh"
<%= selected_items.include?(item) ? "checked" : "" %>
<%= @presenter.graph.slug == 'students-and-teachers' || @presenter.source.slug == 'all-data' ? "disabled" : "" %>
<%= @presenter.group.slug == name ? "" : "hidden" %>>
<label for="<%= id %>"
<%= @presenter.group.slug == name ? "" : "hidden" %>>
<%= label_text %>
</label>
</div>

View file

@ -0,0 +1,41 @@
<h3 class="sub-header-4 mt-5">Data Filters</h3>
<div class="bg-gray p-3" data-controller="analyze">
<% @presenter.sources.each do |source| %>
<input type="radio"
id="<%= source.slug %>"
class="form-check-input"
name="source"
value="<%= base_url %>"
data-action="click->analyze#refresh"
<%= source.slug == @presenter.source.slug ? "checked" : "" %>>
<label for="<%= source.slug %>"><%= source.to_s %></label>
<% source.slices.each do | slice | %>
<div class="mx-3">
<input type="radio"
id="<%= slice.slug %>"
class="form-check-input"
name="slice"
value="<%= base_url %>"
data-action="click->analyze#refresh"
<%= slice.slug == @presenter.slice.slug ? "checked" : "" %>
<%= slice.slug == "all-data" ? "hidden" : "" %>>
<label for="<%= slice.slug %>"
<%= slice.slug == "all-data" ? "hidden" : "" %>>
<%= slice.to_s %></label>
</div>
<% end %>
<% end %>
<%= render partial: "group_selectors" %>
</div>
<script>
window.source = "<%= @presenter.source.slug %>";
window.slice = "<%= @presenter.slice.slug %>";
window.group = "<%= @presenter.group.slug %>";
window.graph = "<%= @presenter.graph.slug %>";
</script>

View file

@ -0,0 +1,14 @@
<h3 class="sub-header-4">Focus Area</h3>
<p>Select a category & subcategory to analyze measure-level results</p>
<select id="select-category" class="mx-3 form-select" data-id="category-dropdown" data-action="analyze#refresh">
<% categories.each do |category| %>
<option value="<%= analyze_category_link(district: district, school: school, academic_year: academic_year, category: category) %>" <%= category.id == @presenter.category.id ? "selected": "" %>><%= "#{category.category_id}: #{category.name}" %></option>
<% end %>
</select>
<select id="select-subcategory" class="mx-3 form-select mt-3" data-id="subcategory-dropdown" data-action="analyze#refresh">
<% subcategories.each do |subcategory| %>
<option value="<%= analyze_subcategory_link(district: district, school: school, academic_year: academic_year, category: category, subcategory: subcategory) %>" <%= subcategory.subcategory_id == @presenter.subcategory.subcategory_id ? "selected": "" %>>
<%= "#{subcategory.subcategory_id}: #{subcategory.name}" %>
</option>
<% end %>
</select>

View file

@ -0,0 +1,30 @@
<g id="graph-background">
<rect x="0" y="0" width="100%" height="<%= background.analyze_zone_height * 2 %>%" fill="#edecf0" />
<rect x="0" y="<%= background.analyze_zone_height * 2 %>%" width="100%" height="<%= background.analyze_zone_height * 3 %>%" fill="#fffaee" />
<rect x="0" y="0" width="100%" height="<%= background.analyze_graph_height %>%" fill="none" stroke="grey" />
<rect x="0" y="<%= background.benchmark_y %>%" width="100%" height="<%= background.benchmark_height %>%" fill="black" />
<g id="zone-dividers" stroke-width="1">
<line x1="0" y1="17%" x2="100%" y2="17%" stroke="white" />
<line x1="0" y1="51%" x2="100%" y2="51%" stroke="#edecf0" />
<line x1="0" y1="68%" x2="100%" y2="68%" stroke="#edecf0" />
</g>
<g id="zone-labels">
<text class="zone-header" x="<%= background.zone_label_x %>%" y="<%= background.zone_label_y(1) %>%" text-anchor="start" dominant-baseline="middle">
Ideal
</text>
<text class="zone-header" x="<%= background.zone_label_x %>%" y="<%= background.zone_label_y(2) %>%" text-anchor="start" dominant-baseline="middle">
Approval
</text>
<text class="zone-header" x="<%= background.zone_label_x %>%" y="<%= background.zone_label_y(3) %>%" text-anchor="start" dominant-baseline="middle">
Growth
</text>
<text class="zone-header" x="<%= background.zone_label_x %>%" y="<%= background.zone_label_y(4) %>%" text-anchor="start" dominant-baseline="middle">
Watch
</text>
<text class="zone-header" x="<%= background.zone_label_x %>%" y="<%= background.zone_label_y(5) %>%" text-anchor="start" dominant-baseline="middle">
Warning
</text>
</g>
</g>

View file

@ -0,0 +1,31 @@
<select id="select-group" name="group" class="mx-4 form-select" data-id="group-dropdown" data-action="analyze#refresh">
<% @presenter.groups.each do |group| %>
<option id="<%= group.slug %>" name="group-option" value="<%= base_url %>" <%= group.slug == @presenter.group.slug ? "Selected": "" %>><%= group.name %> </option>
<% end %>
</select>
<p class="sub-header-5 mx-4 mt-3 font-size-14"> Select a group </p>
<% @presenter.races.each do |race| %>
<%= render(partial: "checkboxes", locals: {id: "race-#{race.slug}", item: race, selected_items: @presenter.selected_races, name: "race", label_text: race.designation}) %>
<% end %>
<% @presenter.grades.each do |grade| %>
<%= render(partial: "checkboxes", locals: {id: "grade-#{grade}", item: grade, selected_items: @presenter.selected_grades, name: "grade", label_text: grade}) %>
<% end %>
<% @presenter.genders.each do |gender| %>
<%= render(partial: "checkboxes", locals: {id: "gender-#{gender.designation}", item: gender, selected_items: @presenter.selected_genders, name: "gender", label_text: gender.designation}) %>
<% end %>
<% @presenter.incomes.each do |income| %>
<%= render(partial: "checkboxes", locals: {id: "income-#{income.slug}", item: income, selected_items: @presenter.selected_incomes, name: "income", label_text: income.label}) %>
<% end %>
<% @presenter.ells.each do |ell| %>
<%= render(partial: "checkboxes", locals: {id: "ell-#{ell.slug}", item: ell, selected_items: @presenter.selected_ells, name: "ell", label_text: ell.designation}) %>
<% end %>
<% @presenter.speds.each do |sped| %>
<%= render(partial: "checkboxes", locals: {id: "sped-#{sped.slug}", item: sped, selected_items: @presenter.selected_speds, name: "sped", label_text: sped.designation}) %>
<% end %>

View file

@ -0,0 +1,10 @@
<svg width="100%" height="<%= svg_height %>">
<%= render partial: "graph_background", locals: {background: @background} %>
<% number_of_columns = @presenter.graph.columns.length %>
<% @presenter.graph.columns.each_with_index do |column, index| %>
<% p = column.new(measure: measure, school: @school, academic_years: @presenter.selected_academic_years, position: index , number_of_columns:) %>
<%= render partial: "grouped_bar_column", locals: {column: p} %>
<% end %>
</svg>

After

Width:  |  Height:  |  Size: 493 B

View file

@ -0,0 +1,53 @@
<g class="grouped-bar-column" data-for-measure-id="<%= column.measure.measure_id %>">
<% score_label_y = [5, 10, 15, 5, 10, 15 ] %>
<% column.bars.each_with_index do |bar, index| %>
<% if column.sufficient_data?(index) %>
<rect
<% if column.show_popover? %>
data-bs-toggle="popover"
data-bs-placement="right"
data-bs-content="<%= column.popover_content(index) %>"
<% end %>
data-for-academic-year="<%= bar.academic_year.range %>"
x="<%= bar.x_position %>%"
y="<%= bar.y_offset %>%"
width="<%= column.bar_width %>%"
height="<%= bar.bar_height_percentage %>%"
fill="<%= bar.color %>" />
<% if ENV["SCORES"].present? && ENV["SCORES"].upcase == "SHOW" %>
<text x="<%= bar.x_position + (column.bar_width * 0.5) %>%" y="<%= score_label_y[index] %>%" text-anchor="middle" dominant-baseline="middle">
<%= bar.average %>
</text>
<% end %>
<% end %>
<% end %>
<line x1="<%= column.column_start_x %>%" y1="0" x2="<%= column.column_start_x %>%" y2="85%" stroke="grey" stroke-width="1" stroke-dasharray="5,2" />
<% words = column.label %>
<% words.each_with_index do | line, index | %>
<text class="graph-footer" x="<%= column.column_midpoint %>%" y="<%= column.bar_label_height + (index * 5) %>%" text-anchor="middle" dominant-baseline="middle" data-grouped-bar-label="<%= column.label %>">
<%= line %>
</text>
<% end %>
<% if column.show_irrelevancy_message? %>
<rect x="<%= column.message_x %>%" y="<%= column.message_y %>%" rx="15" ry="15" width="<%= column.message_width %>%" height="<%= column.message_height %>%" fill="white" stroke="gray" />
<text x="<%= column.column_midpoint %>%" y="<%= 20 %>%" text-anchor="middle">
<tspan x="<%= column.column_midpoint %>%" y="29%">measure not</tspan>
<tspan x="<%= column.column_midpoint %>%" y="34%">based on</tspan>
<tspan x="<%= column.column_midpoint %>%" y="39%"><%= column.basis %></tspan>
</text>
<% elsif column.show_insufficient_data_message? %>
<rect x="<%= column.message_x %>%" y="<%= column.message_y %>%" rx="15" ry="15" width="<%= column.message_width %>%" height="<%= column.message_height %>%" fill="white" stroke="gray" />
<text x="<%= column.column_midpoint %>%" y="<%= 20 %>%" text-anchor="middle">
<% column.insufficiency_message.each_with_index do |line, index| %>
<% offset = 29 + index * 5 %>
<tspan x='<%= column.column_midpoint %>%' y='<%= offset %>%'><%= line %></tspan>
<% end %>
</text>
<% end %>
</g>

View file

@ -0,0 +1,34 @@
<h3 class="sub-header-4 mt-5">School Years</h3>
<% available_academic_years.each_with_index do | year, index | %>
<div class="d-flex justify-content-start align-items-center mt-1" data-controller="analyze">
<input type="checkbox"
class="form-check-input"
id="<%= year.range %>"
name="year-checkbox"
value="<%= analyze_subcategory_link(district: district, school: school, academic_year: academic_year, category: category, subcategory: subcategory) %>"
<%= selected_academic_years.include?(year) ? "checked" : "" %>
data-action="click->analyze#refresh"
<% empty_dataset = empty_dataset?(measures: measures, school: school, academic_year: year) %>
<% empty_survey_dataset = empty_survey_dataset?(measures: measures, school: school, academic_year: year) %>
<% if graph.slug == 'all-data' %>
<%= empty_dataset ? "disabled" : "" %>
<% else %>
<%= empty_survey_dataset ? "disabled" : "" %>
<% end %>
>
<label class="px-3" for="<%= year.range %>"><%= year.range %></label><br>
<div class="bg-color-blue px-3" style="width:20px;height:20px;background-color:<%= colors[index] %>;"></div>
<% if graph.slug == 'all-data' && empty_dataset %>
<i class="fa-solid fa-circle-exclamation px-3"
data-bs-toggle="popover" data-bs-placement="right"
data-bs-content="No admin data OR teacher and student survey response rates below <%= Dashboard::ResponseRate::TEACHER_RATE_THRESHOLD %>%">
</i>
<% end %>
<% if graph.slug != 'all-data' && empty_survey_dataset %>
<i class="fa-solid fa-circle-exclamation px-3"
data-bs-toggle="popover" data-bs-placement="right"
data-bs-content="Teacher and student survey response rates below <%= Dashboard::ResponseRate::TEACHER_RATE_THRESHOLD %>%">
</i>
<% end %>
</div>
<% end %>

View file

@ -0,0 +1,27 @@
<% content_for :title do %>
<h1 class="sub-header-2 color-white m-0"> Analysis of <%= @school.name %> </h1>
<% end %>
<div class="graph-content">
<div class="breadcrumbs sub-header-4">
<%= @presenter.category.category_id %>:<%= @presenter.category.name %> > <%= @presenter.subcategory.subcategory_id %>:<%= @presenter.subcategory.name %>
</div>
<hr>
</div>
<div class="d-flex flex-row pt-5 row">
<div class="d-flex flex-column flex-grow-6 bg-color-white col-3 px-5" data-controller="analyze">
<%= render partial: "focus_area", locals: {categories: @presenter.categories, district: @district, school: @school, academic_year: @academic_year, category: @presenter.category, subcategories: @presenter.subcategories} %>
<%= render partial: "school_years", locals: {available_academic_years: @presenter.academic_years, selected_academic_years: @presenter.selected_academic_years, district: @district, school: @school, academic_year: @academic_year, category: @presenter.category, subcategory: @presenter.subcategory, measures: @presenter.measures, graph: @presenter.graph} %>
<%= render partial: "data_filters", locals: {district: @district, school: @school, academic_year: @academic_year, category: @presenter.category, subcategory: @presenter.subcategory} %>
</div>
<% cache [@school, @presenter.cache_objects] do %>
<div class="bg-color-white flex-grow-1 col-9">
<% @presenter.measures.each do |measure| %>
<section class="mb-6">
<p class="construct-id">Measure <%= measure.measure_id %></p>
<h2> <%= measure.name %> </h2>
<%= render partial: "grouped_bar_chart" , locals: { measure: measure} %>
</section>
<% end %>
</div>
<% end %>
</div>