parent
a538eb72f2
commit
f71f88a4ac
@ -1,8 +1,10 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class AnalyzeController < SqmApplicationController
|
module Dashboard
|
||||||
def index
|
class AnalyzeController < SqmApplicationController
|
||||||
@presenter = Analyze::Presenter.new(params:, school: @school, academic_year: @academic_year)
|
def index
|
||||||
@background ||= BackgroundPresenter.new(num_of_columns: @presenter.graph.columns.count)
|
@presenter = Analyze::Presenter.new(params:, school: @school, academic_year: @academic_year)
|
||||||
|
@background ||= BackgroundPresenter.new(num_of_columns: @presenter.graph.columns.count)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class CategoriesController < SqmApplicationController
|
module Dashboard
|
||||||
helper GaugeHelper
|
class CategoriesController < SqmApplicationController
|
||||||
|
helper GaugeHelper
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@categories = Category.sorted.map { |category| CategoryPresenter.new(category:) }
|
@categories = Category.sorted.map { |category| CategoryPresenter.new(category:) }
|
||||||
|
|
||||||
@category = CategoryPresenter.new(category: Category.find_by_slug(params[:id]))
|
@category = CategoryPresenter.new(category: Category.find_by_slug(params[:id]))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -0,0 +1,42 @@
|
|||||||
|
<div class="accordion-item">
|
||||||
|
<h3 class="accordion-header measure-accordion-header" id="<%= data_item_section.id %>-header">
|
||||||
|
<button
|
||||||
|
class="accordion-button measure-accordion-button collapsed"
|
||||||
|
data-bs-toggle="collapse"
|
||||||
|
data-bs-target="#<%= data_item_section.id %>"
|
||||||
|
aria-expanded="false"
|
||||||
|
aria-controls="<%= data_item_section.id %>"
|
||||||
|
>
|
||||||
|
<%= data_item_section.title %>
|
||||||
|
<% unless data_item_section.sufficient_data? %>
|
||||||
|
<i class="fa-solid fa-circle-exclamation" data-exclamation-point="<%= data_item_section.id %>"></i>
|
||||||
|
<% end %>
|
||||||
|
</button>
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<div
|
||||||
|
id="<%= data_item_section.id %>"
|
||||||
|
class="accordion-collapse collapse"
|
||||||
|
aria-labelledby="<%= data_item_section.id %>-header"
|
||||||
|
data-bs-parent="#<%= data_item_section.data_item_accordion_id %>"
|
||||||
|
>
|
||||||
|
<div class="accordion-body measure-accordion-body font-cabin font-size-14 weight-400">
|
||||||
|
<% unless data_item_section.sufficient_data? %>
|
||||||
|
<div class="alert alert-secondary" role="alert" data-insufficient-data-message="<%= data_item_section.id + '-' + data_item_section.reason_for_insufficiency %>">
|
||||||
|
Data not included due to <%= data_item_section.reason_for_insufficiency %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<ul>
|
||||||
|
<% data_item_section.descriptions_and_availability.each do |data| %>
|
||||||
|
<li><%= data.description %>
|
||||||
|
<% unless data.available? %>
|
||||||
|
<i class="fa-solid fa-circle-exclamation" data-missing-data="<%= data.id %>"
|
||||||
|
data-bs-toggle="popover" data-bs-placement="right"
|
||||||
|
data-bs-content="Data not included due to limited availability"></i>
|
||||||
|
<% end %>
|
||||||
|
</li>
|
||||||
|
<% end %>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,59 @@
|
|||||||
|
<div class="d-flex flex-column align-items-center position-relative">
|
||||||
|
<% if ENV["SCORES"].present? && ENV["SCORES"].upcase == "SHOW" %>
|
||||||
|
<p>Score is : <%= gauge.score %> </p>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<svg
|
||||||
|
viewBox="<%= viewbox.x %> <%= viewbox.y %> <%= viewbox.width %> <%= viewbox.height %>"
|
||||||
|
class="<%= gauge_class %>"
|
||||||
|
>
|
||||||
|
<% if gauge.score_percentage.present? %>
|
||||||
|
<path
|
||||||
|
class="gauge-fill <%= gauge.color_class %>"
|
||||||
|
d="<%= move_to(point: arc_start_point) %>
|
||||||
|
<%= draw_arc(radius: outer_radius, percentage: gauge.score_percentage, clockwise: true) %>
|
||||||
|
<%= draw_line_to(point: arc_end_line_destination(radius: inner_radius, percentage: gauge.score_percentage)) %>
|
||||||
|
<%= draw_arc(radius: inner_radius, percentage: 0, clockwise: false) %>
|
||||||
|
<%= draw_line_to(point: arc_end_line_destination(radius: outer_radius, percentage: 0)) %>"
|
||||||
|
fill="none"
|
||||||
|
stroke="none"
|
||||||
|
/>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
|
||||||
|
<path
|
||||||
|
class="gauge-outline stroke-gray-2"
|
||||||
|
d="<%= move_to(point: arc_start_point) %>
|
||||||
|
<%= draw_arc(radius: outer_radius, percentage: 1, clockwise: true) %>
|
||||||
|
<%= draw_line_to(point: arc_end_line_destination(radius: inner_radius, percentage: 1)) %>
|
||||||
|
<%= draw_arc(radius: inner_radius, percentage: 0, clockwise: false) %>
|
||||||
|
<%= draw_line_to(point: arc_end_line_destination(radius: outer_radius, percentage: 0)) %>"
|
||||||
|
fill="none"
|
||||||
|
stroke-width="<%= stroke_width %>"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<% benchmark_boundaries = [:watch_low, :growth_low, :ideal_low]%>
|
||||||
|
<% benchmark_boundaries.each do |zone| %>
|
||||||
|
<line
|
||||||
|
class="zone-benchmark stroke-gray-2"
|
||||||
|
x1="<%= benchmark_line_point(outer_radius, angle_for(percentage: gauge.boundary_percentage_for(zone))).x %>"
|
||||||
|
y1="<%= benchmark_line_point(outer_radius, angle_for(percentage: gauge.boundary_percentage_for(zone))).y %>"
|
||||||
|
x2="<%= benchmark_line_point(inner_radius, angle_for(percentage: gauge.boundary_percentage_for(zone))).x %>"
|
||||||
|
y2="<%= benchmark_line_point(inner_radius, angle_for(percentage: gauge.boundary_percentage_for(zone))).y %>"
|
||||||
|
stroke-width="<%= stroke_width %>"
|
||||||
|
/>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<% if gauge.key_benchmark_percentage.present? %>
|
||||||
|
<line
|
||||||
|
class="zone-benchmark stroke-black"
|
||||||
|
x1="<%= benchmark_line_point(outer_radius + 5, angle_for(percentage: gauge.key_benchmark_percentage)).x %>"
|
||||||
|
y1="<%= benchmark_line_point(outer_radius + 5, angle_for(percentage: gauge.key_benchmark_percentage)).y %>"
|
||||||
|
x2="<%= benchmark_line_point(inner_radius - 5 , angle_for(percentage: gauge.key_benchmark_percentage)).x %>"
|
||||||
|
y2="<%= benchmark_line_point(inner_radius - 5, angle_for(percentage: gauge.key_benchmark_percentage)).y %>"
|
||||||
|
stroke-width="<%= stroke_width + 2 %>"
|
||||||
|
/>
|
||||||
|
<% end %>
|
||||||
|
</svg>
|
||||||
|
<span class="gauge-title <%= font_class %> fill-black"><%= gauge.title %></span>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
<div id="<%= measure_presenter.id %>" class="measure-section mx-4">
|
||||||
|
<p class="construct-id">Measure <%= measure_presenter.id %></p>
|
||||||
|
<h3 class="measure-description sub-header-4 mb-5 "><%= measure_presenter.name %></h3>
|
||||||
|
<div>
|
||||||
|
<%= render partial: "gauge_graph", locals: { gauge: measure_presenter.gauge_presenter, gauge_class: 'gauge-graph-sm', font_class: 'weight-700' } %>
|
||||||
|
</div>
|
||||||
|
<p class="measure-description body-small mt-5 mb-4"><%= measure_presenter.description %></p>
|
||||||
|
|
||||||
|
<div class="measure-accordion accordion" id="<%= measure_presenter.data_item_accordion_id %>">
|
||||||
|
<%= render partial: "data_item_section", collection: measure_presenter.data_item_presenters %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,59 @@
|
|||||||
|
<section class="subcategory-section">
|
||||||
|
<div id="<%= subcategory.id %>" class="p-7">
|
||||||
|
<p class="construct-id">Subcategory <%= subcategory.id %></p>
|
||||||
|
<h2 class="sub-header-2 font-bitter mb-7"><%= subcategory.name %></h2>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-between align-items-end">
|
||||||
|
<div>
|
||||||
|
<%= render partial: "gauge_graph", locals: { gauge: subcategory.gauge_presenter, gauge_class: 'gauge-graph-lg', font_class: 'sub-header-3' } %>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex flex-column mx-7">
|
||||||
|
<p class="body-large "><%= subcategory.description %></p>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-start">
|
||||||
|
<div
|
||||||
|
class="body-large text-center response-rate"
|
||||||
|
data-bs-toggle="popover"
|
||||||
|
data-bs-trigger="hover focus"
|
||||||
|
data-bs-content="The number of publicly available school data sources, often collected from the MA Department of Elementary and Secondary Education."
|
||||||
|
data-bs-placement="bottom"
|
||||||
|
>
|
||||||
|
<p class="response-rate-percentage"><%= subcategory.admin_collection_rate.first %> / <%= subcategory.admin_collection_rate.last %></p>
|
||||||
|
<p>school admin data sources</p>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="body-large mx-3 text-center response-rate"
|
||||||
|
data-bs-toggle="popover"
|
||||||
|
data-bs-trigger="hover focus"
|
||||||
|
data-bs-content="The student survey response rate for this sub-category. This number differs from the overall response rate because each individual student receives 44 of 67 total questions, in order to avoid survey fatigue."
|
||||||
|
data-bs-placement="bottom"
|
||||||
|
>
|
||||||
|
<p class="response-rate-percentage"><%= subcategory.student_response_rate %></p>
|
||||||
|
<p>of students responded</p>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="body-large text-center response-rate"
|
||||||
|
data-bs-toggle="popover"
|
||||||
|
data-bs-trigger="hover focus"
|
||||||
|
data-bs-content="The teacher survey response rate for this sub-category. This number differs from the overall response rate because the survey includes skip logic to limit the number of questions for each individual survey respondent."
|
||||||
|
data-bs-placement="bottom"
|
||||||
|
>
|
||||||
|
<p class="response-rate-percentage"><%= subcategory.teacher_response_rate %></p>
|
||||||
|
<p>of teachers responded</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="arrow-container mt-7">
|
||||||
|
<div class="arrow-shadow"></div>
|
||||||
|
<div class="arrow"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="measure-card d-flex p-7">
|
||||||
|
<% subcategory.measure_presenters.each do |measure_presenter| %>
|
||||||
|
<%= render partial: "measures_section", locals: { measure_presenter: measure_presenter } %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
<% content_for :navigation do %>
|
||||||
|
<nav class="nav nav-tabs align-self-end">
|
||||||
|
<% @categories.each do |category| %>
|
||||||
|
<div class="nav-item">
|
||||||
|
<%= link_to [@district, @school, category, { year: @academic_year.range }], class: ["nav-link", current_page?([@district, @school, category, { year: @academic_year.range }]) ? "active" : ""] do %>
|
||||||
|
<i class="<%= category.icon_class %> <%= category.icon_color_class if current_page?([@district, @school, category, { year: @academic_year.range }]) %> me-2" ></i>
|
||||||
|
<%= category.name %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
</nav>
|
||||||
|
<select id="select-academic-year" class="form-select" name="academic-year">
|
||||||
|
<% @academic_years.each do |year| %>
|
||||||
|
<option value="<%= url_for [@district, @school, @category , {year: year.range} ]%>" <%= @academic_year == year ? "selected" : nil %>><%= year.formatted_range %></option>
|
||||||
|
<% end %>
|
||||||
|
</select>
|
||||||
|
<% end %>
|
||||||
|
<% cache [@category, @school, @academic_year] do %>
|
||||||
|
<p class="construct-id">Category <%= @category.id %></p>
|
||||||
|
<h1 class="sub-header font-bitter color-red"><%= @category.name %></h1>
|
||||||
|
<p class="col-8 body-large"><%= @category.description %></p>
|
||||||
|
<% @category.subcategories(academic_year: @academic_year, school: @school).each do |subcategory| %>
|
||||||
|
<%= render partial: "subcategory_section", locals: {subcategory: subcategory} %>
|
||||||
|
<% end %>
|
||||||
|
<% end %>
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
module StringMonkeyPatches
|
||||||
|
def valid_likert_score?
|
||||||
|
to_i.between? 1, 5
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
String.include StringMonkeyPatches
|
||||||
Loading…
Reference in new issue