parent
5bc9d27b64
commit
94c5b1acba
@ -1,46 +0,0 @@
|
||||
// Place all the styles related to the Questions controller here.
|
||||
// They will automatically be included in application.css.
|
||||
// You can use Sass (SCSS) here: http://sass-lang.com/
|
||||
|
||||
.question {
|
||||
.question-text {
|
||||
height: 3em;
|
||||
}
|
||||
|
||||
.answers {
|
||||
width: 100%;
|
||||
border-bottom: 1px solid #ccc;
|
||||
|
||||
.answer {
|
||||
border-top: 1px solid #ccc;
|
||||
|
||||
.text {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
td {
|
||||
line-height: 2em;
|
||||
div {
|
||||
margin: 0.25em 0;
|
||||
height: 1.5em;
|
||||
}
|
||||
}
|
||||
|
||||
.bar0 {
|
||||
background-color: #00008b;
|
||||
}
|
||||
.bar1 {
|
||||
background-color: #ADD8E6;
|
||||
}
|
||||
.bar2 {
|
||||
background-color: #4B0082;
|
||||
}
|
||||
.bar3 {
|
||||
background-color: #EE82EE;
|
||||
}
|
||||
.bar4 {
|
||||
background-color: #FFC0CB;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,81 +0,0 @@
|
||||
@import 'variables';
|
||||
|
||||
body {
|
||||
color: #333;
|
||||
font-family: 'Roboto', sans-serif; font-size: 13px;
|
||||
line-height: 18px;
|
||||
margin: 33px;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.notice, .alert, .subscription, .highlight {
|
||||
margin-top: 12px;
|
||||
padding: 24px;
|
||||
text-align: center;
|
||||
border-radius: 12px;
|
||||
a, a:hover, a:visited {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.notice {
|
||||
background-color: $lightgreen;
|
||||
}
|
||||
|
||||
.alert {
|
||||
background-color: $lightred;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
background-color: $lightyellow;
|
||||
}
|
||||
|
||||
.faq {
|
||||
color: $link;
|
||||
}
|
||||
|
||||
header {
|
||||
border-bottom: 1px solid $primary-color;
|
||||
margin-bottom: 30px;
|
||||
|
||||
a, a:hover, a:visited {
|
||||
color: $darkgrey;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
footer {
|
||||
height: 90px;
|
||||
border-top: 1px solid #ccc;
|
||||
padding-top: 12px;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
form {
|
||||
.form-group {
|
||||
padding-top: 12px;
|
||||
|
||||
label {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.form-check-collection {
|
||||
.form-check-label {
|
||||
display: block;
|
||||
padding-bottom: 12px;
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 978px) {
|
||||
.container {
|
||||
padding:0;
|
||||
margin:0;
|
||||
}
|
||||
|
||||
body {
|
||||
padding:0;
|
||||
}
|
||||
}
|
||||
@ -1,117 +0,0 @@
|
||||
.school_category, .question {
|
||||
border: 1px solid black;
|
||||
|
||||
.title {
|
||||
height: 3.5em;
|
||||
}
|
||||
|
||||
.description {
|
||||
height: 6em;
|
||||
}
|
||||
}
|
||||
|
||||
.indicator-container {
|
||||
&.centered {
|
||||
margin-top: -3px;
|
||||
|
||||
.indicator-circle {
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.indicator {
|
||||
padding-top: 6px;
|
||||
height: 90px;
|
||||
|
||||
.indicator-circle {
|
||||
height: 100%;
|
||||
position: relative;
|
||||
|
||||
.indicator-zones {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
div {
|
||||
height: 100%;
|
||||
width: 20%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.zone0 {
|
||||
background-color: orange;
|
||||
}
|
||||
.zone1 {
|
||||
background-color: yellow;
|
||||
}
|
||||
.zone2 {
|
||||
background-color: lightgreen;
|
||||
}
|
||||
.zone3 {
|
||||
background-color: green;
|
||||
}
|
||||
.zone4 {
|
||||
background: repeating-linear-gradient(45deg, lightgray, green 15px);
|
||||
}
|
||||
}
|
||||
|
||||
.average {
|
||||
position: absolute;
|
||||
width: 10%;
|
||||
height: 107%;
|
||||
top: -3px;
|
||||
border: 2px dashed black;
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
|
||||
span {
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
width: 7.75em;
|
||||
margin-top: -1.5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.small {
|
||||
height: 87px;
|
||||
|
||||
.indicator-circle {
|
||||
width: 90px;
|
||||
overflow: hidden;
|
||||
|
||||
.indicator-zones {
|
||||
width: 900px;
|
||||
}
|
||||
|
||||
.average {
|
||||
border: none;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
line-height: 90px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.short {
|
||||
.indicator {
|
||||
height: 30px;
|
||||
|
||||
.indicator-circle {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.average {
|
||||
height: 120%;
|
||||
|
||||
span {
|
||||
left: -1.5em;
|
||||
font-size: 10px;
|
||||
border: none;
|
||||
line-height: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
$primary-color: #9e9e9e; // grey
|
||||
$darkgrey: #212121;
|
||||
$lightgrey: #e0e0e0;
|
||||
$lightgreen: #C8E6C9; // lightgreen
|
||||
$lightred: #FFCDD2; // lightred
|
||||
$lightyellow: #fcf5e2; // lightyellow
|
||||
$orange: #ffab40; // orange
|
||||
$link: #007bff;
|
||||
@ -1,5 +0,0 @@
|
||||
module Legacy
|
||||
class AdminController < Legacy::ApplicationController
|
||||
def index; end
|
||||
end
|
||||
end
|
||||
@ -1,22 +0,0 @@
|
||||
module Legacy
|
||||
class ApplicationController < ActionController::Base
|
||||
protect_from_forgery with: :exception, prepend: true
|
||||
|
||||
layout 'legacy/application'
|
||||
|
||||
def verify_admin
|
||||
return true # if current_user.admin?(@school)
|
||||
|
||||
redirect_to root_path, notice: 'You must be logged in as an admin of that school to access that page.'
|
||||
false
|
||||
end
|
||||
|
||||
def authenticate(username, password)
|
||||
return true if username == 'boston'
|
||||
|
||||
authenticate_or_request_with_http_basic do |u, p|
|
||||
u == username && p == password
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,99 +0,0 @@
|
||||
module Legacy
|
||||
class AttemptsController < Legacy::ApplicationController
|
||||
# before_action :set_attempt, only: [:edit, :update]
|
||||
protect_from_forgery except: [:twilio]
|
||||
|
||||
def twilio
|
||||
recipient = Recipient.where(phone: twilio_params['From']).first
|
||||
attempt = recipient.attempts.last_sent.first
|
||||
|
||||
all_twilio_details = (attempt.twilio_details || '').split('~!~')
|
||||
all_twilio_details << twilio_params.to_h.to_yaml
|
||||
|
||||
attempt.save_response(
|
||||
answer_index: twilio_params[:Body].to_i > 0 ? twilio_params[:Body].to_i : nil,
|
||||
twilio_details: all_twilio_details.join('~!~')
|
||||
)
|
||||
|
||||
unless %w[start resume restart yes go].index(twilio_params[:Body].downcase).nil?
|
||||
recipient.update(opted_out: false)
|
||||
render plain: 'Thank you, you will now begin receiving messages again.'
|
||||
return
|
||||
end
|
||||
|
||||
unless %w[stop cancel quit no].index(twilio_params[:Body].downcase).nil?
|
||||
recipient.update(opted_out: true)
|
||||
render plain: 'Thank you, you have been opted out of these messages and will no longer receive them.'
|
||||
return
|
||||
end
|
||||
|
||||
unless ['skip', 'i dont know', "i don't know", 'next'].index(twilio_params[:Body].downcase).nil?
|
||||
render plain: 'Thank you, this question has been skipped.'
|
||||
return
|
||||
end
|
||||
|
||||
response_message = ["We've registered your response of \"#{attempt.response}\"."]
|
||||
|
||||
answer_count = Attempt.for_question(attempt.question).for_school(recipient.school).with_answer.count
|
||||
if answer_count > 1
|
||||
response_message << "#{answer_count} people have responded to this question so far. To see all responses visit:"
|
||||
else
|
||||
response_message << 'You are the first person to respond to this question. Once more people have responded you will be able to see all responses at:'
|
||||
end
|
||||
response_message << legacy_school_legacy_category_url(attempt.recipient.school, attempt.question.category)
|
||||
|
||||
render plain: response_message.join(' ')
|
||||
end
|
||||
|
||||
# # GET /attempts/1/edit
|
||||
# def edit
|
||||
# end
|
||||
#
|
||||
# # PATCH/PUT /attempts/1
|
||||
# # PATCH/PUT /attempts/1.json
|
||||
# def update
|
||||
# attempt_params = {}
|
||||
# if twilio_params.present?
|
||||
# attempt_params.merge!(
|
||||
# answer_index: twilio_params[:Body].to_i,
|
||||
# twilio_details: twilio_params.to_h.to_yaml
|
||||
# )
|
||||
# end
|
||||
#
|
||||
# respond_to do |format|
|
||||
# if @attempt.update(attempt_params)
|
||||
# format.html { render plain: 'Thank you!' }
|
||||
# format.json { render :show, status: :ok, location: @attempt }
|
||||
# else
|
||||
# format.html { render :edit }
|
||||
# format.json { render json: @attempt.errors, status: :unprocessable_entity }
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
|
||||
# # DELETE /attempts/1
|
||||
# # DELETE /attempts/1.json
|
||||
# def destroy
|
||||
# @attempt.destroy
|
||||
# respond_to do |format|
|
||||
# format.html { redirect_to attempts_url, notice: 'attempt was successfully destroyed.' }
|
||||
# format.json { head :no_content }
|
||||
# end
|
||||
# end
|
||||
|
||||
private
|
||||
|
||||
# Use callbacks to share common setup or constraints between actions.
|
||||
def set_attempt
|
||||
@attempt = Attempt.find(params[:id])
|
||||
end
|
||||
|
||||
# Never trust parameters from the scary internet, only allow the white list through.
|
||||
def twilio_params
|
||||
{ 'Body' => '5', '' => 'US', 'To' => '+16172023890', 'ToZip' => '02135', 'NumSegments' => '1',
|
||||
'MessageSid' => 'SMe37977e625b7f0b429339e752dddefef', 'AccountSid' => 'AC57dc8a5a6d75addb9528e730e92f66b2', 'From' => '+16502693205', 'ApiVersion' => '2010-04-01' }
|
||||
params.permit(:FromCountry, :FromState, :FromZip, :FromCity, :ToCountry, :ToState, :SmsStatus, :SmsSid,
|
||||
:SmsMessageSid, :MessageSid, :AccountSid, :MessagingServiceSid, :From, :To, :Body, :NumMedia)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,106 +0,0 @@
|
||||
module Legacy
|
||||
class CategoriesController < Legacy::ApplicationController
|
||||
before_action :set_school, only: [:show]
|
||||
before_action :set_category, only: %i[show edit update destroy]
|
||||
|
||||
# GET /categories
|
||||
# GET /categories.json
|
||||
def index
|
||||
@categories = Legacy::Category.all
|
||||
end
|
||||
|
||||
# GET /categories/1
|
||||
# GET /categories/1.json
|
||||
def show
|
||||
district = @school.district
|
||||
authenticate(district.name.downcase, "#{district.name.downcase}!")
|
||||
|
||||
school_categories = SchoolCategory.for(@school, @category)
|
||||
@years = school_categories.map(&:year).map(&:to_i).sort
|
||||
@year = (params[:year] || @years.last || '2019').to_i
|
||||
|
||||
if school_categories.empty?
|
||||
school_categories = [SchoolCategory.new(school: @school, category: @category, year: @year)]
|
||||
end
|
||||
|
||||
@school_category = school_categories.select { |sc| sc.year.to_s == @year.to_s }.first
|
||||
@child_school_categories = SchoolCategory.for_parent_category(@school, @category).in(@year).valid.to_a
|
||||
missing_categories = Legacy::Category.for_parent(@category) - @child_school_categories.map(&:category)
|
||||
missing_categories.each do |category|
|
||||
next if category.benchmark.present?
|
||||
|
||||
@child_school_categories << category.school_categories.new(school: @school)
|
||||
end
|
||||
|
||||
@child_school_categories = @child_school_categories.reject { |csc| csc.admin? } if district.name == 'Boston'
|
||||
|
||||
@questions = @category.questions.created_in(@year)
|
||||
end
|
||||
|
||||
# GET /categories/new
|
||||
def new
|
||||
@category = Legacy::Category.new
|
||||
end
|
||||
|
||||
# GET /categories/1/edit
|
||||
def edit; end
|
||||
|
||||
# POST /categories
|
||||
# POST /categories.json
|
||||
def create
|
||||
@category = Legacy::Category.new(category_params)
|
||||
|
||||
respond_to do |format|
|
||||
if @category.save
|
||||
format.html { redirect_to @category, notice: 'Category was successfully created.' }
|
||||
format.json { render :show, status: :created, location: @category }
|
||||
else
|
||||
format.html { render :new }
|
||||
format.json { render json: @category.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# PATCH/PUT /categories/1
|
||||
# PATCH/PUT /categories/1.json
|
||||
def update
|
||||
respond_to do |format|
|
||||
if @category.update(category_params)
|
||||
format.html { redirect_to @category, notice: 'Category was successfully updated.' }
|
||||
format.json { render :show, status: :ok, location: @category }
|
||||
else
|
||||
format.html { render :edit }
|
||||
format.json { render json: @category.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# DELETE /categories/1
|
||||
# DELETE /categories/1.json
|
||||
def destroy
|
||||
@category.destroy
|
||||
respond_to do |format|
|
||||
format.html { redirect_to legacy_categories_url, notice: 'Category was successfully destroyed.' }
|
||||
format.json { head :no_content }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_school
|
||||
redirect_to root_path and return false unless params.include?(:school_id)
|
||||
|
||||
@school = Legacy::School.friendly.find(params[:school_id])
|
||||
redirect_to root_path and return false if @school.nil?
|
||||
end
|
||||
|
||||
def set_category
|
||||
@category = Legacy::Category.friendly.find(params[:id])
|
||||
end
|
||||
|
||||
# Never trust parameters from the scary internet, only allow the white list through.
|
||||
def category_params
|
||||
params.require(:category).permit(:name, :blurb, :description, :external_id, :parent_category_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,78 +0,0 @@
|
||||
module Legacy
|
||||
class DistrictsController < Legacy::ApplicationController
|
||||
before_action :set_district, only: %i[show edit update destroy]
|
||||
|
||||
# GET /districts
|
||||
# GET /districts.json
|
||||
def index
|
||||
@districts = Legacy::District.all.alphabetic
|
||||
end
|
||||
|
||||
# GET /districts/1
|
||||
# GET /districts/1.json
|
||||
def show
|
||||
authenticate(@district.name.downcase, "#{@district.name.downcase}!")
|
||||
@schools = @district.schools.alphabetic
|
||||
end
|
||||
|
||||
# GET /districts/new
|
||||
def new
|
||||
@district = Legacy::District.new
|
||||
end
|
||||
|
||||
# GET /districts/1/edit
|
||||
def edit; end
|
||||
|
||||
# POST /districts
|
||||
# POST /districts.json
|
||||
def create
|
||||
@district = Legacy::District.new(district_params)
|
||||
|
||||
respond_to do |format|
|
||||
if @district.save
|
||||
format.html { redirect_to @district, notice: 'District was successfully created.' }
|
||||
format.json { render :show, status: :created, location: @district }
|
||||
else
|
||||
format.html { render :new }
|
||||
format.json { render json: @district.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# PATCH/PUT /districts/1
|
||||
# PATCH/PUT /districts/1.json
|
||||
def update
|
||||
respond_to do |format|
|
||||
if @district.update(district_params)
|
||||
format.html { redirect_to @district, notice: 'District was successfully updated.' }
|
||||
format.json { render :show, status: :ok, location: @district }
|
||||
else
|
||||
format.html { render :edit }
|
||||
format.json { render json: @district.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# DELETE /districts/1
|
||||
# DELETE /districts/1.json
|
||||
def destroy
|
||||
@district.destroy
|
||||
respond_to do |format|
|
||||
format.html { redirect_to districts_url, notice: 'District was successfully destroyed.' }
|
||||
format.json { head :no_content }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Use callbacks to share common setup or constraints between actions.
|
||||
def set_district
|
||||
@district = Legacy::District.find_by_slug(params[:id])
|
||||
end
|
||||
|
||||
# Never trust parameters from the scary internet, only allow the white list through.
|
||||
def district_params
|
||||
params.require(:district).permit(:name, :state_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,75 +0,0 @@
|
||||
module Legacy
|
||||
class QuestionListsController < Legacy::ApplicationController
|
||||
before_action :set_question_list, only: %i[show edit update destroy]
|
||||
|
||||
# GET /question_lists
|
||||
# GET /question_lists.json
|
||||
def index
|
||||
@question_lists = QuestionList.all
|
||||
end
|
||||
|
||||
# GET /question_lists/1
|
||||
# GET /question_lists/1.json
|
||||
def show; end
|
||||
|
||||
# GET /question_lists/new
|
||||
def new
|
||||
@question_list = QuestionList.new
|
||||
end
|
||||
|
||||
# GET /question_lists/1/edit
|
||||
def edit; end
|
||||
|
||||
# POST /question_lists
|
||||
# POST /question_lists.json
|
||||
def create
|
||||
@question_list = QuestionList.new(question_list_params)
|
||||
|
||||
respond_to do |format|
|
||||
if @question_list.save
|
||||
format.html { redirect_to @question_list, notice: 'Question list was successfully created.' }
|
||||
format.json { render :show, status: :created, location: @question_list }
|
||||
else
|
||||
format.html { render :new }
|
||||
format.json { render json: @question_list.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# PATCH/PUT /question_lists/1
|
||||
# PATCH/PUT /question_lists/1.json
|
||||
def update
|
||||
respond_to do |format|
|
||||
if @question_list.update(question_list_params)
|
||||
format.html { redirect_to @question_list, notice: 'Question list was successfully updated.' }
|
||||
format.json { render :show, status: :ok, location: @question_list }
|
||||
else
|
||||
format.html { render :edit }
|
||||
format.json { render json: @question_list.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# DELETE /question_lists/1
|
||||
# DELETE /question_lists/1.json
|
||||
def destroy
|
||||
@question_list.destroy
|
||||
respond_to do |format|
|
||||
format.html { redirect_to legacy_question_lists_url, notice: 'Question list was successfully destroyed.' }
|
||||
format.json { head :no_content }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Use callbacks to share common setup or constraints between actions.
|
||||
def set_question_list
|
||||
@question_list = QuestionList.find(params[:id])
|
||||
end
|
||||
|
||||
# Never trust parameters from the scary internet, only allow the white list through.
|
||||
def question_list_params
|
||||
params.require(:question_list).permit(:name, :description, question_id_array: [])
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,89 +0,0 @@
|
||||
module Legacy
|
||||
class QuestionsController < Legacy::ApplicationController
|
||||
before_action :authenticate_user!, except: [:show]
|
||||
before_action :verify_super_admin, except: [:show]
|
||||
before_action :set_school, only: [:show]
|
||||
before_action :set_question, only: %i[show edit update destroy]
|
||||
|
||||
# GET /questions
|
||||
# GET /questions.json
|
||||
def index
|
||||
@questions = Question.all
|
||||
end
|
||||
|
||||
# GET /questions/1
|
||||
# GET /questions/1.json
|
||||
def show; end
|
||||
|
||||
# GET /questions/new
|
||||
def new
|
||||
@question = Question.new
|
||||
end
|
||||
|
||||
# GET /questions/1/edit
|
||||
def edit; end
|
||||
|
||||
# POST /questions
|
||||
# POST /questions.json
|
||||
def create
|
||||
@question = Question.new(question_params)
|
||||
|
||||
respond_to do |format|
|
||||
if @question.save
|
||||
format.html { redirect_to @question, notice: 'Question was successfully created.' }
|
||||
format.json { render :show, status: :created, location: @question }
|
||||
else
|
||||
format.html { render :new }
|
||||
format.json { render json: @question.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# PATCH/PUT /questions/1
|
||||
# PATCH/PUT /questions/1.json
|
||||
def update
|
||||
respond_to do |format|
|
||||
if @question.update(question_params)
|
||||
format.html { redirect_to @question, notice: 'Question was successfully updated.' }
|
||||
format.json { render :show, status: :ok, location: @question }
|
||||
else
|
||||
format.html { render :edit }
|
||||
format.json { render json: @question.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# DELETE /questions/1
|
||||
# DELETE /questions/1.json
|
||||
def destroy
|
||||
@question.destroy
|
||||
respond_to do |format|
|
||||
format.html { redirect_to legacy_questions_url, notice: 'Question was successfully destroyed.' }
|
||||
format.json { head :no_content }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_school
|
||||
redirect_to root_path and return false unless params.include?(:school_id)
|
||||
|
||||
@school = Legacy::School.friendly.find(params[:school_id])
|
||||
redirect_to root_path and return false if @school.nil?
|
||||
end
|
||||
|
||||
# Use callbacks to share common setup or constraints between actions.
|
||||
def set_question
|
||||
@question = Question.find(params[:id])
|
||||
end
|
||||
|
||||
# Never trust parameters from the scary internet, only allow the white list through.
|
||||
def question_params
|
||||
params.require(:question).permit(:text, :option1, :option2, :option3, :option4, :option5, :category_id)
|
||||
end
|
||||
|
||||
def verify_super_admin
|
||||
user_signed_in? && current_user.super_admin?
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,67 +0,0 @@
|
||||
module Legacy
|
||||
class RecipientListsController < Legacy::ApplicationController
|
||||
before_action :authenticate_user!
|
||||
before_action :set_school
|
||||
before_action :verify_admin
|
||||
before_action :set_recipient_list, only: %i[show edit update destroy]
|
||||
|
||||
# GET schools/1/recipient_lists
|
||||
def index
|
||||
@recipient_lists = @school.recipient_lists
|
||||
end
|
||||
|
||||
# GET schools/1/recipient_lists/1
|
||||
def show; end
|
||||
|
||||
# GET schools/1/recipient_lists/new
|
||||
def new
|
||||
@recipient_list = @school.recipient_lists.build
|
||||
end
|
||||
|
||||
# GET schools/1/recipient_lists/1/edit
|
||||
def edit; end
|
||||
|
||||
# POST schools/1/recipient_lists
|
||||
def create
|
||||
@recipient_list = @school.recipient_lists.build(recipient_list_params)
|
||||
|
||||
if @recipient_list.save
|
||||
redirect_to([@recipient_list.school, @recipient_list], notice: 'Recipient list was successfully created.')
|
||||
else
|
||||
render action: 'new'
|
||||
end
|
||||
end
|
||||
|
||||
# PUT schools/1/recipient_lists/1
|
||||
def update
|
||||
if @recipient_list.update(recipient_list_params)
|
||||
redirect_to([@recipient_list.school, @recipient_list], notice: 'Recipient list was successfully updated.')
|
||||
else
|
||||
render action: 'edit'
|
||||
end
|
||||
end
|
||||
|
||||
# DELETE schools/1/recipient_lists/1
|
||||
def destroy
|
||||
@recipient_list.destroy
|
||||
|
||||
redirect_to @school
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Use callbacks to share common setup or constraints between actions.
|
||||
def set_school
|
||||
@school = Legacy::School.friendly.find(params[:school_id])
|
||||
end
|
||||
|
||||
def set_recipient_list
|
||||
@recipient_list = @school.recipient_lists.find(params[:id])
|
||||
end
|
||||
|
||||
# Only allow a trusted parameter "white list" through.
|
||||
def recipient_list_params
|
||||
params.require(:recipient_list).permit(:name, :description, recipient_id_array: [])
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,97 +0,0 @@
|
||||
module Legacy
|
||||
class RecipientsController < Legacy::ApplicationController
|
||||
before_action :authenticate_user!
|
||||
before_action :set_school
|
||||
before_action :verify_admin
|
||||
before_action :set_recipient, only: %i[show edit update destroy]
|
||||
|
||||
# GET /recipients
|
||||
# GET /recipients.json
|
||||
def index
|
||||
@recipients = @school.recipients.all
|
||||
end
|
||||
|
||||
# GET /recipients/1
|
||||
# GET /recipients/1.json
|
||||
def show; end
|
||||
|
||||
# GET /recipients/new
|
||||
def new
|
||||
@recipient = @school.recipients.new
|
||||
end
|
||||
|
||||
# GET /recipients/1/edit
|
||||
def edit; end
|
||||
|
||||
# POST /recipients
|
||||
# POST /recipients.json
|
||||
def create
|
||||
@recipient = @school.recipients.new(recipient_params)
|
||||
|
||||
respond_to do |format|
|
||||
if @recipient.save
|
||||
format.html do
|
||||
redirect_to legacy_school_legacy_recipient_path(@school, @recipient),
|
||||
notice: 'Recipient was successfully created.'
|
||||
end
|
||||
format.json { render :show, status: :created, location: @recipient }
|
||||
else
|
||||
format.html { render :new }
|
||||
format.json { render json: @recipient.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def import
|
||||
render and return if request.get?
|
||||
|
||||
Recipient.import(@school, params[:file])
|
||||
redirect_to @school, notice: 'Recipients imported.'
|
||||
end
|
||||
|
||||
# PATCH/PUT /recipients/1
|
||||
# PATCH/PUT /recipients/1.json
|
||||
def update
|
||||
respond_to do |format|
|
||||
if @recipient.update(recipient_params)
|
||||
format.html do
|
||||
redirect_to legacy_school_legacy_recipient_path(@school, @recipient),
|
||||
notice: 'Recipient was successfully updated.'
|
||||
end
|
||||
format.json { render :show, status: :ok, location: @recipient }
|
||||
else
|
||||
format.html { render :edit }
|
||||
format.json { render json: @recipient.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# DELETE /recipients/1
|
||||
# DELETE /recipients/1.json
|
||||
def destroy
|
||||
@recipient.destroy
|
||||
respond_to do |format|
|
||||
format.html { redirect_to @school, notice: 'Recipient was successfully destroyed.' }
|
||||
format.json { head :no_content }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Use callbacks to share common setup or constraints between actions.
|
||||
def set_school
|
||||
@school = Legacy::School.friendly.find(params[:school_id])
|
||||
end
|
||||
|
||||
# Use callbacks to share common setup or constraints between actions.
|
||||
def set_recipient
|
||||
@recipient = @school.recipients.find(params[:id])
|
||||
end
|
||||
|
||||
# Never trust parameters from the scary internet, only allow the white list through.
|
||||
def recipient_params
|
||||
params.require(:recipient).permit(:name, :phone, :birth_date, :gender, :race, :ethnicity, :home_language_id,
|
||||
:income, :opted_out, :school_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,70 +0,0 @@
|
||||
module Legacy
|
||||
class SchedulesController < Legacy::ApplicationController
|
||||
before_action :authenticate_user!, except: [:show]
|
||||
before_action :set_school
|
||||
before_action :verify_admin
|
||||
before_action :set_schedule, only: %i[show edit update destroy]
|
||||
before_action :set_time, only: %i[create update]
|
||||
|
||||
# GET schools/1/schedules/1
|
||||
def show; end
|
||||
|
||||
# GET schools/1/schedules/new
|
||||
def new
|
||||
@schedule = @school.schedules.build
|
||||
end
|
||||
|
||||
# GET schools/1/schedules/1/edit
|
||||
def edit; end
|
||||
|
||||
# POST schools/1/schedules
|
||||
def create
|
||||
@schedule = @school.schedules.build(schedule_params)
|
||||
|
||||
if @schedule.save
|
||||
redirect_to([@schedule.school, @schedule], notice: 'Schedule was successfully created.')
|
||||
else
|
||||
render action: 'new'
|
||||
end
|
||||
end
|
||||
|
||||
# PUT schools/1/schedules/1
|
||||
def update
|
||||
if @schedule.update(schedule_params)
|
||||
redirect_to([@schedule.school, @schedule], notice: 'Schedule was successfully updated.')
|
||||
else
|
||||
render action: 'edit'
|
||||
end
|
||||
end
|
||||
|
||||
# DELETE schools/1/schedules/1
|
||||
def destroy
|
||||
@schedule.destroy
|
||||
|
||||
redirect_to @school
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Use callbacks to share common setup or constraints between actions.
|
||||
def set_school
|
||||
@school = Legacy::School.friendly.find(params[:school_id])
|
||||
end
|
||||
|
||||
def set_schedule
|
||||
@schedule = @school.schedules.find(params[:id])
|
||||
end
|
||||
|
||||
# Only allow a trusted parameter "white list" through.
|
||||
def schedule_params
|
||||
params.require(:schedule).permit(:name, :description, :school_id, :frequency_hours, :start_date, :end_date,
|
||||
:time, :active, :random, :recipient_list_id, :question_list_id)
|
||||
end
|
||||
|
||||
def set_time
|
||||
return unless schedule_params.include?(:time)
|
||||
|
||||
params[:schedule][:time] = schedule_params[:time].to_i + (4 * 60) # Go from EST to UTC (NEEDS TO BETTER)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,94 +0,0 @@
|
||||
module Legacy
|
||||
class SchoolsController < Legacy::ApplicationController
|
||||
before_action :authenticate_user!, except: [:show]
|
||||
before_action :set_school, only: %i[admin show edit update destroy]
|
||||
before_action :verify_admin, except: %i[show create new]
|
||||
|
||||
# GET /schools/1
|
||||
# GET /schools/1.json
|
||||
def show
|
||||
@district = @school.district
|
||||
authenticate(@district.name.downcase, "#{@district.name.downcase}!")
|
||||
|
||||
@years = [2017, 2018, 2019]
|
||||
@year = (params[:year] || @years.last).to_i
|
||||
|
||||
if @district.name == 'Boston'
|
||||
@categories = Legacy::Category.joins(:questions)
|
||||
@school_categories = SchoolCategory.where(school: @school).where(category: @categories).in(@year).to_a
|
||||
else
|
||||
@categories = Legacy::Category.root
|
||||
@school_categories = @school.school_categories.for_parent_category(@school, nil).valid.in(@year).sort
|
||||
end
|
||||
|
||||
missing_categories = @categories - @school_categories.map(&:category)
|
||||
missing_categories.each do |category|
|
||||
@school_categories << category.school_categories.new(school: @school, year: @year)
|
||||
end
|
||||
|
||||
@school_categories = @school_categories.select { |sc| sc.year.to_i == @year }
|
||||
end
|
||||
|
||||
def admin; end
|
||||
|
||||
# GET /schools/new
|
||||
def new
|
||||
@school = Legacy::School.new
|
||||
end
|
||||
|
||||
# GET /schools/1/edit
|
||||
def edit; end
|
||||
|
||||
# POST /schools
|
||||
# POST /schools.json
|
||||
def create
|
||||
@school = Legacy::School.new(school_params)
|
||||
|
||||
respond_to do |format|
|
||||
if @school.save
|
||||
format.html { redirect_to @school, notice: 'School was successfully created.' }
|
||||
format.json { render :show, status: :created, location: @school }
|
||||
else
|
||||
format.html { render :new }
|
||||
format.json { render json: @school.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# PATCH/PUT /schools/1
|
||||
# PATCH/PUT /schools/1.json
|
||||
def update
|
||||
respond_to do |format|
|
||||
if @school.update(school_params)
|
||||
format.html { redirect_to @school, notice: 'School was successfully updated.' }
|
||||
format.json { render :show, status: :ok, location: @school }
|
||||
else
|
||||
format.html { render :edit }
|
||||
format.json { render json: @school.errors, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# DELETE /schools/1
|
||||
# DELETE /schools/1.json
|
||||
def destroy
|
||||
@school.destroy
|
||||
respond_to do |format|
|
||||
format.html { redirect_to legacy_schools_url, notice: 'School was successfully destroyed.' }
|
||||
format.json { head :no_content }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Use callbacks to share common setup or constraints between actions.
|
||||
def set_school
|
||||
@school = Legacy::School.friendly.find(params[:id] || params[:school_id])
|
||||
end
|
||||
|
||||
# Never trust parameters from the scary internet, only allow the white list through.
|
||||
def school_params
|
||||
params.require(:school).permit(:name, :district_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,16 +0,0 @@
|
||||
module Legacy
|
||||
class UsersController < Legacy::ApplicationController
|
||||
def show; end
|
||||
|
||||
# private
|
||||
# # Use callbacks to share common setup or constraints between actions.
|
||||
# def set_district
|
||||
# @district = District.find(params[:id])
|
||||
# end
|
||||
#
|
||||
# # Never trust parameters from the scary internet, only allow the white list through.
|
||||
# def district_params
|
||||
# params.require(:district).permit(:name, :state_id)
|
||||
# end
|
||||
end
|
||||
end
|
||||
@ -1,8 +0,0 @@
|
||||
module Legacy
|
||||
class WelcomeController < Legacy::ApplicationController
|
||||
def index
|
||||
@districts = Legacy::District.all.alphabetic
|
||||
@schools = Legacy::School.all.alphabetic
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,7 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Legacy
|
||||
def self.table_name_prefix
|
||||
'legacy_'
|
||||
end
|
||||
end
|
||||
@ -1,91 +0,0 @@
|
||||
module Legacy
|
||||
class Attempt < ApplicationRecord
|
||||
belongs_to :schedule
|
||||
belongs_to :recipient
|
||||
belongs_to :recipient_schedule
|
||||
belongs_to :question
|
||||
belongs_to :student
|
||||
|
||||
after_save :update_school_categories
|
||||
after_commit :update_counts
|
||||
|
||||
scope :for_question, ->(question) { where(question_id: question.id) }
|
||||
scope :for_recipient, ->(recipient) { where(recipient_id: recipient.id) }
|
||||
scope :for_student, ->(student) { where(student_id: student.id) }
|
||||
scope :for_category, ->(category) { joins(:question).merge(Question.for_category(category)) }
|
||||
scope :for_school, ->(school) { joins(:recipient).merge(Legacy::Recipient.for_school(school)) }
|
||||
scope :with_answer, -> { where("answer_index is not null or open_response_id is not null") }
|
||||
scope :with_no_answer, -> { where("answer_index is null and open_response_id is null") }
|
||||
scope :not_yet_responded, -> { where(responded_at: nil) }
|
||||
scope :last_sent, -> { order(sent_at: :desc) }
|
||||
scope :created_in, ->(year) { where("extract(year from legacy_attempts.created_at) = ?", year) }
|
||||
|
||||
def messages
|
||||
child_specific = student.present? ? " (for #{student.name})" : ""
|
||||
|
||||
cancel_text = "\nSkip question: skip\nStop all questions: stop"
|
||||
|
||||
[
|
||||
"#{question.text}#{child_specific}",
|
||||
"#{question.option1}: Reply 1\n#{question.option2}: 2\n#{question.option3}: 3\n#{question.option4}: 4\n#{question.option5}: 5"
|
||||
]
|
||||
end
|
||||
|
||||
def send_message
|
||||
twilio_number = ENV["TWILIO_NUMBER"]
|
||||
client = Twilio::REST::Client.new ENV["TWILIO_ACCOUNT_SID"], ENV["TWILIO_AUTH_TOKEN"]
|
||||
|
||||
sids = []
|
||||
messages.each do |message|
|
||||
sids << client.messages.create(
|
||||
from: twilio_number,
|
||||
to: recipient.phone,
|
||||
body: message
|
||||
).sid
|
||||
end
|
||||
|
||||
update(sent_at: Time.new, twilio_sid: sids.join(","))
|
||||
recipient.update(phone: client.messages.get(sids.last).to)
|
||||
end
|
||||
|
||||
def response
|
||||
return "No Answer Yet" if answer_index.blank?
|
||||
|
||||
question.options[answer_index_with_reverse - 1]
|
||||
end
|
||||
|
||||
def save_response(answer_index: nil, twilio_details: nil, responded_at: Time.new)
|
||||
update(
|
||||
answer_index:,
|
||||
twilio_details:,
|
||||
responded_at:
|
||||
)
|
||||
|
||||
recipient_schedule.update(next_attempt_at: Time.new) if recipient_schedule.queued_question_ids.present?
|
||||
end
|
||||
|
||||
def answer_index_with_reverse
|
||||
return 6 - answer_index if question.reverse?
|
||||
|
||||
answer_index
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def update_school_categories
|
||||
return if ENV["BULK_PROCESS"]
|
||||
|
||||
school_category = SchoolCategory.for(recipient.school, question.category).first
|
||||
if school_category.nil?
|
||||
school_category = SchoolCategory.create(school: recipient.school, category: question.category)
|
||||
end
|
||||
school_category.sync_aggregated_responses
|
||||
end
|
||||
|
||||
def update_counts
|
||||
return if ENV["BULK_PROCESS"]
|
||||
|
||||
recipient.update_counts
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,93 +0,0 @@
|
||||
module Legacy
|
||||
class Category < ApplicationRecord
|
||||
has_many :questions
|
||||
belongs_to :parent_category, class_name: 'Legacy::Category', foreign_key: :parent_category_id
|
||||
has_many :child_categories, class_name: 'Legacy::Category', foreign_key: :parent_category_id
|
||||
has_many :school_categories
|
||||
|
||||
validates :name, presence: true
|
||||
|
||||
scope :for_parent, ->(category = nil) { where(parent_category_id: category.try(:id)) }
|
||||
scope :likert, -> { where('benchmark is null') }
|
||||
|
||||
include FriendlyId
|
||||
friendly_id :name, use: [:slugged]
|
||||
|
||||
def path
|
||||
p = self
|
||||
items = [p]
|
||||
items << p while (p = p.try(:parent_category))
|
||||
items.uniq.compact.reverse
|
||||
end
|
||||
|
||||
def root_identifier
|
||||
path.first.name.downcase.gsub(/\s/, '-')
|
||||
end
|
||||
|
||||
def root_index
|
||||
Category.root_identifiers.index(root_identifier) || 0
|
||||
end
|
||||
|
||||
def self.root_identifiers
|
||||
%w[
|
||||
teachers-and-the-teaching-environment
|
||||
school-culture
|
||||
resources
|
||||
academic-learning
|
||||
community-and-wellbeing
|
||||
pilot-family-questions
|
||||
]
|
||||
end
|
||||
|
||||
def self.root
|
||||
Category.where(parent_category: nil).select { |c| root_identifiers.index(c.slug) }
|
||||
end
|
||||
|
||||
def custom_zones
|
||||
return [] if zones.nil?
|
||||
|
||||
zones.split(',').map(&:to_f)
|
||||
end
|
||||
|
||||
def zone_widths
|
||||
return nil if zones.nil?
|
||||
|
||||
widths = custom_zones.each_with_index.map do |zone, index|
|
||||
(zone - (index == 0 ? 0 : custom_zones[index - 1])).round(2)
|
||||
end
|
||||
|
||||
widths[4] = widths[4] + (5 - widths.sum)
|
||||
widths
|
||||
end
|
||||
|
||||
def sync_child_zones
|
||||
likert_child_categories = child_categories.likert
|
||||
return unless likert_child_categories.present?
|
||||
|
||||
total_zones = [0, 0, 0, 0, 0]
|
||||
valid_child_categories = 0
|
||||
likert_child_categories.each do |cc|
|
||||
cc.sync_child_zones if cc.zones.nil?
|
||||
|
||||
if cc.zones.nil?
|
||||
puts "NO ZONES: #{name} -> #{cc.name}"
|
||||
else
|
||||
valid_child_categories += 1
|
||||
|
||||
puts "ZONES: #{name} | #{cc.name} | #{cc.zones}"
|
||||
|
||||
cc.custom_zones.each_with_index do |zone, index|
|
||||
puts "ZONE: #{name} | #{zone} | #{index}"
|
||||
total_zones[index] += zone
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if valid_child_categories > 0
|
||||
average_zones = total_zones.map { |zone| zone / valid_child_categories }
|
||||
puts "TOTAL: #{name} | #{total_zones} | #{valid_child_categories} | #{average_zones} | #{zone_widths}"
|
||||
update(zones: average_zones.join(','))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,17 +0,0 @@
|
||||
module Legacy
|
||||
class District < ApplicationRecord
|
||||
has_many :schools
|
||||
|
||||
validates :name, presence: true
|
||||
|
||||
scope :alphabetic, -> { order(name: :asc) }
|
||||
|
||||
include FriendlyId
|
||||
|
||||
friendly_id :name, use: [:slugged]
|
||||
|
||||
before_save do
|
||||
self.slug ||= name.parameterize
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,75 +0,0 @@
|
||||
AggregatedResponses = Struct.new(
|
||||
:question,
|
||||
:category,
|
||||
:responses,
|
||||
:count,
|
||||
:answer_index_total,
|
||||
:answer_index_average,
|
||||
:most_popular_answer,
|
||||
:zscore
|
||||
)
|
||||
|
||||
module Legacy
|
||||
class Question < ApplicationRecord
|
||||
belongs_to :category
|
||||
|
||||
has_many :attempts
|
||||
|
||||
validates :text, presence: true
|
||||
validates :option1, presence: true
|
||||
validates :option2, presence: true
|
||||
validates :option3, presence: true
|
||||
validates :option4, presence: true
|
||||
validates :option5, presence: true
|
||||
|
||||
scope :for_category, ->(category) { where(category:) }
|
||||
scope :created_in, ->(year) { where("extract(year from #{table_name}.created_at) = ?", year) }
|
||||
|
||||
enum :target_group, %i[unknown for_students for_teachers for_parents]
|
||||
|
||||
def source
|
||||
target_group.gsub("for_", "")
|
||||
end
|
||||
|
||||
def options
|
||||
[option1, option2, option3, option4, option5]
|
||||
end
|
||||
|
||||
def options_with_reverse
|
||||
return options.reverse if reverse?
|
||||
|
||||
options
|
||||
end
|
||||
|
||||
def option_index(answer)
|
||||
options_with_reverse.map(&:downcase).map(&:strip).index(answer.downcase.strip)
|
||||
end
|
||||
|
||||
def aggregated_responses_for_school(school)
|
||||
school_responses = attempts.for_school(school).with_answer.order(id: :asc)
|
||||
return unless school_responses.present?
|
||||
|
||||
response_answer_total = school_responses.inject(0) do |total, response|
|
||||
total + response.answer_index_with_reverse
|
||||
end
|
||||
histogram = school_responses.group_by(&:answer_index_with_reverse)
|
||||
|
||||
most_popular_answer_index = histogram.to_a.sort_by { |info| info[1].length }.last[0]
|
||||
most_popular_answer = options_with_reverse[most_popular_answer_index - 1]
|
||||
|
||||
AggregatedResponses.new(
|
||||
self,
|
||||
category,
|
||||
school_responses,
|
||||
school_responses.length,
|
||||
response_answer_total,
|
||||
response_answer_total.to_f / school_responses.length.to_f,
|
||||
most_popular_answer
|
||||
)
|
||||
end
|
||||
|
||||
def normalized_text
|
||||
text.gsub("[science/math/English/social studies]", "")
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,29 +0,0 @@
|
||||
module Legacy
|
||||
class QuestionList < ApplicationRecord
|
||||
validates :name, presence: true
|
||||
validates :question_ids, presence: true
|
||||
|
||||
attr_accessor :question_id_array
|
||||
|
||||
before_validation :convert_question_id_array
|
||||
after_initialize :set_question_id_array
|
||||
|
||||
def questions
|
||||
question_id_array.collect { |id| Question.where(id:).first }.compact
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def convert_question_id_array
|
||||
return if question_id_array.blank?
|
||||
|
||||
self.question_ids = question_id_array.reject { |id| id.to_s.empty? }.join(',')
|
||||
end
|
||||
|
||||
def set_question_id_array
|
||||
return if question_ids.blank?
|
||||
|
||||
self.question_id_array = question_ids.split(',').map(&:to_i)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,50 +0,0 @@
|
||||
module Legacy
|
||||
class Recipient < ApplicationRecord
|
||||
belongs_to :school
|
||||
validates_associated :school
|
||||
|
||||
has_many :recipient_schedules
|
||||
has_many :attempts
|
||||
|
||||
has_many :students
|
||||
|
||||
validates :name, presence: true
|
||||
|
||||
scope :for_school, ->(school) { where(school:) }
|
||||
scope :created_in, ->(year) { where('extract(year from recipients.created_at) = ?', year) }
|
||||
|
||||
before_destroy :sync_lists
|
||||
|
||||
def self.import(school, file)
|
||||
CSV.foreach(file.path, headers: true) do |row|
|
||||
school.recipients.create!(row.to_hash)
|
||||
# recipient_hash = row.to_hash
|
||||
# recipient = school.recipients.where(phone: recipient_hash["phone"])
|
||||
#
|
||||
# if recipient.count == 1
|
||||
# recipient.first.update(recipient_hash)
|
||||
# else
|
||||
# school.recipients.create!(recipient_hash)
|
||||
# end
|
||||
end
|
||||
end
|
||||
|
||||
def update_counts
|
||||
update(
|
||||
attempts_count: attempts.count,
|
||||
responses_count: attempts.with_answer.count
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def sync_lists
|
||||
school.recipient_lists.each do |recipient_list|
|
||||
next if recipient_list.recipient_id_array.index(id).nil?
|
||||
|
||||
updated_ids = recipient_list.recipient_id_array - [id]
|
||||
recipient_list.update(recipient_id_array: updated_ids)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,52 +0,0 @@
|
||||
module Legacy
|
||||
class RecipientList < ApplicationRecord
|
||||
belongs_to :school
|
||||
has_many :schedules
|
||||
|
||||
validates_associated :school
|
||||
validates :name, presence: true
|
||||
|
||||
attr_accessor :recipient_id_array
|
||||
|
||||
before_validation :convert_recipient_id_array
|
||||
after_initialize :set_recipient_id_array
|
||||
|
||||
after_save :sync_recipient_schedules
|
||||
|
||||
def recipients
|
||||
recipient_id_array.collect { |id| school.recipients.where(id:).first }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def convert_recipient_id_array
|
||||
return if recipient_id_array.blank? || (recipient_ids_was != recipient_ids)
|
||||
|
||||
self.recipient_ids = recipient_id_array.reject { |id| id.to_s.empty? }.join(',')
|
||||
end
|
||||
|
||||
def set_recipient_id_array
|
||||
return if recipient_id_array.present?
|
||||
|
||||
self.recipient_id_array = (recipient_ids || '').split(',').map(&:to_i)
|
||||
end
|
||||
|
||||
def sync_recipient_schedules
|
||||
return unless recipient_ids_before_last_save.present? && recipient_ids_before_last_save != recipient_ids
|
||||
|
||||
old_ids = recipient_ids_before_last_save.split(/,/)
|
||||
new_ids = recipient_ids.split(/,/)
|
||||
(old_ids - new_ids).each do |deleted_recipient|
|
||||
schedules.each do |schedule|
|
||||
schedule.recipient_schedules.for_recipient(deleted_recipient).first.destroy
|
||||
end
|
||||
end
|
||||
|
||||
(new_ids - old_ids).each do |new_recipient|
|
||||
schedules.each do |schedule|
|
||||
RecipientSchedule.create_for_recipient(new_recipient, schedule)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,168 +0,0 @@
|
||||
module Legacy
|
||||
class RecipientSchedule < ApplicationRecord
|
||||
belongs_to :recipient
|
||||
belongs_to :schedule
|
||||
has_many :attempts
|
||||
|
||||
validates_associated :recipient
|
||||
validates_associated :schedule
|
||||
validates :next_attempt_at, presence: true
|
||||
|
||||
scope :ready, -> { where('next_attempt_at <= ?', Time.new) }
|
||||
scope :for_recipient, lambda { |recipient_or_recipient_id|
|
||||
id = if recipient_or_recipient_id.is_a?(Recipient)
|
||||
recipient_or_recipient_id.id
|
||||
else
|
||||
recipient_or_recipient_id
|
||||
end
|
||||
where(recipient_id: id)
|
||||
}
|
||||
scope :for_schedule, lambda { |schedule_or_schedule_id|
|
||||
id = if schedule_or_schedule_id.is_a?(Schedule)
|
||||
schedule_or_schedule_id.id
|
||||
else
|
||||
schedule_or_schedule_id
|
||||
end
|
||||
where(schedule_id: id)
|
||||
}
|
||||
|
||||
def next_question
|
||||
next_question_id = if queued_question_ids.present?
|
||||
queued_question_ids.split(/,/).first
|
||||
else
|
||||
upcoming_question_ids.split(/,/).first
|
||||
end
|
||||
Question.where(id: next_question_id).first
|
||||
end
|
||||
|
||||
def upcoming_question_id_array
|
||||
upcoming_question_ids.try(:split, /,/) || []
|
||||
end
|
||||
|
||||
def attempted_question_id_array
|
||||
attempted_question_ids.try(:split, /,/) || []
|
||||
end
|
||||
|
||||
def queued_question_id_array
|
||||
queued_question_ids.try(:split, /,/) || []
|
||||
end
|
||||
|
||||
def attempt_question_for_recipient_students(send_message: true, question: next_question)
|
||||
return if recipient.opted_out?
|
||||
return if question.nil?
|
||||
|
||||
return attempt_question(question:) unless question.for_recipient_students?
|
||||
|
||||
missing_students = []
|
||||
recipient_attempts = attempts.for_recipient(recipient).for_question(question)
|
||||
recipient.students.each do |student|
|
||||
missing_students << student if recipient_attempts.for_student(student).empty?
|
||||
end
|
||||
|
||||
attempt = recipient.attempts.create(
|
||||
schedule:,
|
||||
recipient_schedule: self,
|
||||
question:,
|
||||
student: missing_students.first
|
||||
)
|
||||
|
||||
if send_message && attempt.send_message
|
||||
upcoming = upcoming_question_id_array
|
||||
queued = queued_question_id_array
|
||||
attempted = attempted_question_id_array
|
||||
|
||||
if question.present?
|
||||
question_id = [question.id.to_s]
|
||||
upcoming -= question_id
|
||||
if missing_students.length > 1
|
||||
queued += question_id
|
||||
else
|
||||
attempted += question_id
|
||||
queued -= question_id
|
||||
end
|
||||
end
|
||||
|
||||
update(
|
||||
upcoming_question_ids: upcoming.empty? ? nil : upcoming.join(','),
|
||||
attempted_question_ids: attempted.empty? ? nil : attempted.join(','),
|
||||
queued_question_ids: queued.empty? ? nil : queued.join(','),
|
||||
last_attempt_at: attempt.sent_at,
|
||||
next_attempt_at: next_valid_attempt_time
|
||||
)
|
||||
end
|
||||
attempt
|
||||
end
|
||||
|
||||
def attempt_question(send_message: true, question: next_question)
|
||||
return if recipient.opted_out?
|
||||
|
||||
unanswered_attempt = recipient.attempts.not_yet_responded.last
|
||||
|
||||
return if question.nil? && unanswered_attempt.nil?
|
||||
|
||||
if unanswered_attempt.nil?
|
||||
return attempt_question_for_recipient_students(question:) if question.for_recipient_students?
|
||||
|
||||
attempt = recipient.attempts.create(
|
||||
schedule:,
|
||||
recipient_schedule: self,
|
||||
question:
|
||||
)
|
||||
end
|
||||
|
||||
if send_message && (unanswered_attempt || attempt).send_message
|
||||
upcoming = upcoming_question_id_array
|
||||
queued = queued_question_id_array
|
||||
attempted = attempted_question_id_array
|
||||
|
||||
if question.present?
|
||||
question_id = [question.id.to_s]
|
||||
upcoming -= question_id
|
||||
if unanswered_attempt.nil?
|
||||
attempted += question_id
|
||||
queued -= question_id
|
||||
else
|
||||
queued += question_id
|
||||
end
|
||||
end
|
||||
|
||||
update(
|
||||
upcoming_question_ids: upcoming.empty? ? nil : upcoming.join(','),
|
||||
attempted_question_ids: attempted.empty? ? nil : attempted.join(','),
|
||||
queued_question_ids: queued.empty? ? nil : queued.join(','),
|
||||
last_attempt_at: (unanswered_attempt || attempt).sent_at,
|
||||
next_attempt_at: next_valid_attempt_time
|
||||
)
|
||||
end
|
||||
(unanswered_attempt || attempt)
|
||||
end
|
||||
|
||||
def next_valid_attempt_time
|
||||
local_time = (next_attempt_at + (60 * 60 * schedule.frequency_hours)).in_time_zone('Eastern Time (US & Canada)')
|
||||
local_time += 1.day while local_time.on_weekend?
|
||||
local_time
|
||||
end
|
||||
|
||||
def self.create_for_recipient(recipient_or_recipient_id, schedule, next_attempt_at = nil)
|
||||
if next_attempt_at.nil?
|
||||
next_attempt_at = Time.at(schedule.start_date.to_time.to_i + (60 * schedule.time))
|
||||
next_attempt_at += 1.day while next_attempt_at.on_weekend?
|
||||
end
|
||||
|
||||
question_ids = schedule.question_list.question_ids.split(/,/)
|
||||
question_ids = question_ids.shuffle if schedule.random?
|
||||
|
||||
recipient_id = if recipient_or_recipient_id.is_a?(Recipient)
|
||||
recipient_or_recipient_id.id
|
||||
else
|
||||
recipient_or_recipient_id
|
||||
end
|
||||
|
||||
schedule.recipient_schedules.create(
|
||||
recipient_id:,
|
||||
upcoming_question_ids: question_ids.join(','),
|
||||
next_attempt_at:
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,33 +0,0 @@
|
||||
module Legacy
|
||||
class Schedule < ApplicationRecord
|
||||
belongs_to :school
|
||||
belongs_to :recipient_list
|
||||
belongs_to :question_list
|
||||
has_many :recipient_schedules
|
||||
|
||||
validates :name, presence: true
|
||||
validates :recipient_list, presence: true
|
||||
validates :question_list, presence: true
|
||||
|
||||
before_validation :set_start_date
|
||||
after_create :create_recipient_schedules
|
||||
|
||||
scope :active, lambda {
|
||||
where(active: true).where('start_date <= ? and end_date > ?', Date.today, Date.today)
|
||||
}
|
||||
|
||||
private
|
||||
|
||||
def set_start_date
|
||||
return if start_date.present?
|
||||
|
||||
self.start_date = Date.today
|
||||
end
|
||||
|
||||
def create_recipient_schedules
|
||||
recipient_list.recipients.each do |recipient|
|
||||
RecipientSchedule.create_for_recipient(recipient, self)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,89 +0,0 @@
|
||||
module Legacy
|
||||
class School < ApplicationRecord
|
||||
has_many :schedules, dependent: :destroy
|
||||
has_many :recipient_lists, dependent: :destroy
|
||||
belongs_to :district
|
||||
has_many :recipients, dependent: :destroy
|
||||
has_many :school_categories, dependent: :destroy
|
||||
has_many :user_schools, dependent: :destroy
|
||||
|
||||
validates :name, presence: true
|
||||
|
||||
scope :alphabetic, -> { order(name: :asc) }
|
||||
|
||||
include FriendlyId
|
||||
friendly_id :name, use: [:slugged]
|
||||
|
||||
def self.find_by_district_code_and_school_code(district_code, school_code)
|
||||
School
|
||||
.joins(:district)
|
||||
.where(districts: { qualtrics_code: district_code })
|
||||
.find_by_qualtrics_code(school_code)
|
||||
end
|
||||
|
||||
def available_responders_for(question)
|
||||
if question.for_students?
|
||||
student_count || 1
|
||||
elsif question.for_teachers?
|
||||
teacher_count || 1
|
||||
else
|
||||
1
|
||||
end
|
||||
end
|
||||
|
||||
def merge_into(school_name)
|
||||
school = district.schools.where(name: school_name).first
|
||||
if school.nil?
|
||||
puts "Unable to find school named #{school_name} in district (#{district.name})"
|
||||
return
|
||||
end
|
||||
puts "Merging #{name} (#{id}) in to #{school.name} (#{school.id})"
|
||||
schedules.update_all(school_id: school.id)
|
||||
recipient_lists.update_all(school_id: school.id)
|
||||
recipients.update_all(school_id: school.id)
|
||||
school_categories.each do |school_category|
|
||||
school_category.update(school_id: school.id)
|
||||
existing_school_category = school.school_categories.for(school_category.school,
|
||||
school_category.category).in(school_category.year)
|
||||
if existing_school_category.present?
|
||||
if existing_school_category.attempt_count == 0 && existing_school_category.zscore.nil?
|
||||
existing_school_category.destroy
|
||||
else
|
||||
school_category.destroy
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
reload
|
||||
|
||||
user_schools.update_all(school_id: school.id)
|
||||
|
||||
school.school_categories.map(&:sync_aggregated_responses)
|
||||
|
||||
base_categories = Category.joins(:questions).to_a.flatten.uniq
|
||||
base_categories.each do |category|
|
||||
SchoolCategory.for(school, category).each do |school_category|
|
||||
year = school_category.year
|
||||
dup_school_categories = SchoolCategory.for(school, category).in(year)
|
||||
next unless dup_school_categories.count > 1
|
||||
|
||||
dup_school_categories.each { |dsc| dsc.destroy unless dsc.id == school_category.id }
|
||||
school_category.sync_aggregated_responses
|
||||
parent = category.parent_category
|
||||
until parent.nil?
|
||||
SchoolCategory.for(school, parent).in(year).valid.each do |parent_school_category|
|
||||
parent_dup_school_categories = SchoolCategory.for(school, parent).in(year)
|
||||
if parent_dup_school_categories.count > 1
|
||||
parent_dup_school_categories.each { |pdsc| pdsc.destroy unless pdsc.id == parent_school_category.id }
|
||||
parent_school_category.sync_aggregated_responses
|
||||
end
|
||||
end
|
||||
parent = parent.parent_category
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
destroy
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,106 +0,0 @@
|
||||
module Legacy
|
||||
class SchoolCategory < ApplicationRecord
|
||||
|
||||
MIN_RESPONSE_COUNT = 10
|
||||
|
||||
belongs_to :school
|
||||
belongs_to :category
|
||||
|
||||
has_many :school_questions
|
||||
|
||||
validates_associated :school
|
||||
validates_associated :category
|
||||
|
||||
scope :for, -> (school, category) { where(school: school).where(category: category) }
|
||||
scope :for_parent_category, -> (school, category = nil) { where(school: school).joins(:category).merge(Category.for_parent(category)) }
|
||||
scope :in, -> (year) { where(year: year) }
|
||||
|
||||
scope :valid, -> { where("zscore is not null or valid_child_count is not null") }
|
||||
|
||||
def admin?
|
||||
child_categories = category.child_categories
|
||||
return false if child_categories.blank?
|
||||
child_categories.each { |cc| return false if cc.benchmark.blank? }
|
||||
return true
|
||||
end
|
||||
|
||||
def root_index
|
||||
category.root_index
|
||||
end
|
||||
|
||||
def answer_index_average
|
||||
answer_index_total.to_f / response_count.to_f
|
||||
end
|
||||
|
||||
def aggregated_responses
|
||||
attempt_data = Legacy::Attempt.
|
||||
created_in(year).
|
||||
for_category(category).
|
||||
for_school(school).
|
||||
select('count(legacy_attempts.id) as attempt_count').
|
||||
select('count(legacy_attempts.answer_index) as response_count').
|
||||
select('sum(case when legacy_questions.reverse then 6 - legacy_attempts.answer_index else legacy_attempts.answer_index end) as answer_index_total')[0]
|
||||
|
||||
return {
|
||||
attempt_count: attempt_data.attempt_count || 0,
|
||||
response_count: attempt_data.response_count || 0,
|
||||
answer_index_total: attempt_data.answer_index_total || 0,
|
||||
zscore: attempt_data.answer_index_total.nil? ?
|
||||
(attempt_data.response_count > MIN_RESPONSE_COUNT ? zscore : nil) :
|
||||
(attempt_data.response_count > MIN_RESPONSE_COUNT ?
|
||||
(attempt_data.answer_index_total.to_f / attempt_data.response_count.to_f - 3.to_f) :
|
||||
nil)
|
||||
}
|
||||
end
|
||||
|
||||
def chained_aggregated_responses
|
||||
return {} if nonlikert.present?
|
||||
|
||||
_aggregated_responses = aggregated_responses
|
||||
|
||||
child_school_categories = []
|
||||
if category.child_categories.length > 0
|
||||
child_school_categories = category.child_categories.collect do |cc|
|
||||
SchoolCategory.for(school, cc).in(year).valid
|
||||
end.flatten.compact
|
||||
|
||||
return {} if child_school_categories.blank?
|
||||
end
|
||||
|
||||
average_zscore = nil
|
||||
zscore_categories = child_school_categories.select { |csc| csc.zscore.present? && !csc.zscore.nan? }
|
||||
if zscore_categories.length > 0
|
||||
total_zscore = zscore_categories.inject(0) { |total, zc| total + zc.zscore }
|
||||
average_zscore = total_zscore / zscore_categories.length
|
||||
end
|
||||
|
||||
return {
|
||||
attempt_count:
|
||||
_aggregated_responses[:attempt_count] +
|
||||
child_school_categories.inject(0) { |total, csc| total + (csc.attempt_count || 0) },
|
||||
response_count:
|
||||
_aggregated_responses[:response_count] +
|
||||
child_school_categories.inject(0) { |total, csc| total + (csc.response_count || 0) },
|
||||
answer_index_total:
|
||||
_aggregated_responses[:answer_index_total] +
|
||||
child_school_categories.inject(0) { |total, csc| total + (csc.answer_index_total || 0) },
|
||||
zscore: average_zscore.present? ? average_zscore : _aggregated_responses[:zscore]
|
||||
}
|
||||
end
|
||||
|
||||
def sync_aggregated_responses
|
||||
# This doesn't seem to be taking into account valid_child_count or Boston's "Community and Wellbeing" category which should be suppressed if the "Health" category is the only child category visible.
|
||||
|
||||
return if ENV['BULK_PROCESS']
|
||||
update(chained_aggregated_responses)
|
||||
return if response_count == 0 && zscore.nil?
|
||||
if category.parent_category.present?
|
||||
parent_school_category = SchoolCategory.for(school, category.parent_category).in(year).first
|
||||
if parent_school_category.nil?
|
||||
parent_school_category = SchoolCategory.create(school: school, category: category.parent_category, year: year)
|
||||
end
|
||||
parent_school_category.sync_aggregated_responses
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,33 +0,0 @@
|
||||
module Legacy
|
||||
class SchoolQuestion < ApplicationRecord
|
||||
belongs_to :school
|
||||
belongs_to :question
|
||||
belongs_to :school_category
|
||||
|
||||
validates_associated :school
|
||||
validates_associated :question
|
||||
validates_associated :school_category
|
||||
|
||||
scope :for, ->(school, question) { where(school_id: school.id, question_id: question.id) }
|
||||
scope :in, ->(year) { where(year:) }
|
||||
|
||||
def sync_attempts
|
||||
attempt_data = Attempt
|
||||
.joins(:question)
|
||||
.created_in(school_category.year)
|
||||
.for_question(question)
|
||||
.for_school(school)
|
||||
.select('count(attempts.answer_index) as response_count')
|
||||
.select('sum(case when questions.reverse then 6 - attempts.answer_index else attempts.answer_index end) as answer_index_total')[0]
|
||||
|
||||
available_responders = school.available_responders_for(question)
|
||||
|
||||
update(
|
||||
attempt_count: available_responders,
|
||||
response_count: attempt_data.response_count,
|
||||
response_rate: attempt_data.response_count.to_f / available_responders.to_f,
|
||||
response_total: attempt_data.answer_index_total
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,5 +0,0 @@
|
||||
module Legacy
|
||||
class Student < ApplicationRecord
|
||||
belongs_to :recipient
|
||||
end
|
||||
end
|
||||
@ -1,23 +0,0 @@
|
||||
module Legacy
|
||||
class User < ApplicationRecord
|
||||
# Include default devise modules. Others available are:
|
||||
# :confirmable, :lockable, :timeoutable and :omniauthable
|
||||
devise :database_authenticatable, :registerable,
|
||||
:recoverable, :rememberable, :trackable, :validatable
|
||||
|
||||
has_many :user_schools
|
||||
|
||||
def schools
|
||||
districts = user_schools.map(&:district).compact.uniq
|
||||
(user_schools.map(&:school) + districts.map(&:schools)).flatten.compact.uniq
|
||||
end
|
||||
|
||||
def admin?(school)
|
||||
schools.index(school).present?
|
||||
end
|
||||
|
||||
def super_admin?
|
||||
[1].index(id).present?
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,7 +0,0 @@
|
||||
module Legacy
|
||||
class UserSchool < ApplicationRecord
|
||||
belongs_to :user
|
||||
belongs_to :school
|
||||
belongs_to :district
|
||||
end
|
||||
end
|
||||
@ -1,13 +0,0 @@
|
||||
%header.row
|
||||
.title.col-12
|
||||
.float-right= link_to("Frequently Asked Questions", "/MCIEA-Data-Dashboard-FAQ.pdf", class: 'faq', target: '_blank')
|
||||
%h2{style: "clear: right; text-align: center; margin-bottom: 30px;"}
|
||||
= link_to(image_tag('logo.png'), root_path)
|
||||
|
||||
-#
|
||||
.navigation.col-4.text-right
|
||||
- if current_user
|
||||
= link_to 'Sign Out', destroy_user_session_path, rel: "nofollow", method: :delete, class: 'btn btn-small grey waves-effect waves-light '
|
||||
- else
|
||||
= link_to 'Login', new_user_session_path, class: 'btn btn-small grey waves-effect waves-light '
|
||||
=# link_to 'Register', new_user_registration_path, class: 'btn btn-small grey waves-effect waves-light '
|
||||
@ -1,21 +0,0 @@
|
||||
.row
|
||||
.col
|
||||
=# link_to(image_tag(@district.logo), @district) if @district.present?
|
||||
%h2= link_to @school.name, legacy_school_path(@school, year: @year)
|
||||
= simple_format(@school.description)
|
||||
- if @year.present?
|
||||
%p
|
||||
|
||||
- if @years.present?
|
||||
%p
|
||||
%b Data from:
|
||||
- @years.sort.each do |year|
|
||||
|
||||
- if @school_category.present?
|
||||
= link_to_unless(year == @year, "#{year - 1}-#{year}", legacy_school_legacy_category_path(@school_category.school, @school_category.category, year: year))
|
||||
- else
|
||||
= link_to_unless(year == @year, "#{year - 1}-#{year}", legacy_school_path(@school, year: year))
|
||||
- if @school.district.present?
|
||||
%p
|
||||
%strong District:
|
||||
= link_to @school.district.name, @school.district
|
||||
@ -1,36 +0,0 @@
|
||||
!!!
|
||||
%html
|
||||
%head
|
||||
%meta{:content => "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}/
|
||||
%meta{:charset => "utf-8"}/
|
||||
%meta{:content => "width=device-width, initial-scale=1, shrink-to-fit=no", :name => "viewport"}/
|
||||
%link{href: "https://fonts.googleapis.com/css?family=Bitter:400,600,700", rel: "stylesheet", type: "text/css"}/
|
||||
%link{href: "https://fonts.googleapis.com/css?family=Cabin:400,600,700", rel: "stylesheet", type: "text/css"}/
|
||||
%title MCIEA
|
||||
= csrf_meta_tags
|
||||
= stylesheet_link_tag 'application', media: 'all', 'data-turbo-track': 'reload'
|
||||
= stylesheet_link_tag 'https://fonts.googleapis.com/css?family=Roboto:300,700'
|
||||
= javascript_include_tag 'application', 'data-turbo-track': 'reload'
|
||||
|
||||
/ Global site tag (gtag.js) - Google Analytics
|
||||
%script{:async => "", :src => "https://www.googletagmanager.com/gtag/js?id=UA-132936999-1"}
|
||||
:javascript
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('js', new Date());
|
||||
|
||||
gtag('config', 'UA-132936999-1');
|
||||
|
||||
%body
|
||||
.container
|
||||
.row
|
||||
.col-12
|
||||
= render partial: 'layouts/legacy/header'
|
||||
|
||||
- if notice.present?
|
||||
%p.notice= notice
|
||||
|
||||
- if alert.present?
|
||||
%p.alert= alert
|
||||
|
||||
= yield
|
||||
@ -1,8 +0,0 @@
|
||||
!!!
|
||||
%html
|
||||
%head
|
||||
%meta{:content => "text/html; charset=utf-8", "http-equiv" => "Content-Type"}/
|
||||
:css
|
||||
/* Email styles need to be inline */
|
||||
%body
|
||||
= yield
|
||||
@ -1 +0,0 @@
|
||||
= yield
|
||||
@ -1,3 +0,0 @@
|
||||
%p= link_to 'Categories', legacy_categories_path
|
||||
|
||||
%p= link_to 'Questions', legacy_questions_path
|
||||
@ -1,2 +0,0 @@
|
||||
%p
|
||||
= school_category.category.path.map { |c| link_to(c.name, legacy_school_legacy_category_path(school_category.school, c, year: school_category.year)) }.join(' > ').html_safe
|
||||
@ -1,26 +0,0 @@
|
||||
= form_for(category, as: 'category') do |f|
|
||||
- if category.errors.any?
|
||||
#error_explanation
|
||||
%h2
|
||||
= pluralize(category.errors.count, "error")
|
||||
prohibited this category from being saved:
|
||||
%ul
|
||||
- category.errors.full_messages.each do |message|
|
||||
%li= message
|
||||
.field
|
||||
= f.label :name
|
||||
= f.text_field :name
|
||||
.field
|
||||
= f.label :blurb
|
||||
= f.text_field :blurb
|
||||
.field
|
||||
= f.label :description
|
||||
= f.text_area :description
|
||||
.field
|
||||
= f.label :external_id
|
||||
= f.text_field :external_id
|
||||
.field
|
||||
= f.label :parent_category_id
|
||||
= f.number_field :parent_category_id
|
||||
.actions
|
||||
= f.submit
|
||||
@ -1,3 +0,0 @@
|
||||
- categories = [category]
|
||||
- categories << category while (category = category.parent_category).present?
|
||||
= categories.reverse.map { |category| link_to(category.name, category) }.join(' | ').html_safe
|
||||
@ -1,5 +0,0 @@
|
||||
%h1 Editing Category
|
||||
= render 'form', category: @category
|
||||
= link_to 'Show', @category
|
||||
|
|
||||
= link_to 'Back', legacy_categories_path
|
||||
@ -1,24 +0,0 @@
|
||||
%p#notice= notice
|
||||
%h1 Categories
|
||||
%table
|
||||
%thead
|
||||
%tr
|
||||
%th Name
|
||||
%th Blurb
|
||||
%th Description
|
||||
%th External
|
||||
%th Parent category
|
||||
%th{:colspan => "3"}
|
||||
%tbody
|
||||
- @categories.each do |category|
|
||||
%tr
|
||||
%td= category.name
|
||||
%td= category.blurb
|
||||
%td= category.description
|
||||
%td= category.external_id
|
||||
%td= category.parent_category_id
|
||||
%td= link_to 'Show', category
|
||||
%td= link_to 'Edit', edit_legacy_category_path(category)
|
||||
%td= link_to 'Destroy', category, method: :delete, data: { confirm: 'Are you sure?' }
|
||||
%br/
|
||||
= link_to 'New Category', new_legacy_category_path
|
||||
@ -1,4 +0,0 @@
|
||||
json.array!(@categories) do |category|
|
||||
json.extract! category, :id, :name, :blurb, :description, :external_id, :parent_category_id
|
||||
json.url category_url(category, format: :json)
|
||||
end
|
||||
@ -1,3 +0,0 @@
|
||||
%h1 New Category
|
||||
= render 'form', category: @category
|
||||
= link_to 'Back', legacy_categories_path
|
||||
@ -1,49 +0,0 @@
|
||||
- valid = @school_category.school.district.name != "Boston" || (((@school_category.valid_child_count || 1) > 0) && (@school_category.category.benchmark.blank?))
|
||||
|
||||
= render 'layouts/legacy/school_header'
|
||||
|
||||
- if @school_category.school.district.name != "Boston"
|
||||
.row
|
||||
.col-12
|
||||
%p
|
||||
= render 'legacy/categories/breadcrumbs', school_category: @school_category
|
||||
|
||||
.row
|
||||
.col-12
|
||||
.school_category.p-2
|
||||
%h3.title.text-center.pt-3
|
||||
= @category.name
|
||||
|
||||
%p= @category.description
|
||||
- if valid
|
||||
%p
|
||||
- if @school_category.category.benchmark.present?
|
||||
%b Administrative Data:
|
||||
- if @school_category.nonlikert.present?
|
||||
= @school_category.nonlikert
|
||||
= "(Benchmark: #{@school_category.category.benchmark})"
|
||||
|
||||
- if @school_category.zscore.present?
|
||||
= @school_category.zscore.round(1) + 3
|
||||
(out of 5)
|
||||
|
||||
|
||||
.indicator-container.py-3
|
||||
= render 'legacy/school_categories/indicator', info: @school_category
|
||||
- else
|
||||
.row.py-4
|
||||
.col-12.text-center
|
||||
.px-2
|
||||
%h5 Insufficient Responses
|
||||
%p No data is displayed for this measure because of insufficient responses.
|
||||
|
||||
- unless @school.district.name == "Boston" && @category.slug == "effective-leadership-scale"
|
||||
- if @child_school_categories.present?
|
||||
.row
|
||||
= render @child_school_categories
|
||||
|
||||
- if @questions.present?
|
||||
.row
|
||||
= render @questions
|
||||
|
||||
= render "legacy/shared/performance_spectrum"
|
||||
@ -1 +0,0 @@
|
||||
json.extract! @category, :id, :name, :blurb, :description, :external_id, :parent_category_id, :created_at, :updated_at
|
||||
@ -1,17 +0,0 @@
|
||||
= form_for(district, as: 'district') do |f|
|
||||
- if district.errors.any?
|
||||
#error_explanation
|
||||
%h2
|
||||
= pluralize(district.errors.count, "error")
|
||||
prohibited this district from being saved:
|
||||
%ul
|
||||
- district.errors.full_messages.each do |message|
|
||||
%li= message
|
||||
.field
|
||||
= f.label :name
|
||||
= f.text_field :name
|
||||
.field
|
||||
= f.label :state_id
|
||||
= f.number_field :state_id
|
||||
.actions
|
||||
= f.submit
|
||||
@ -1,5 +0,0 @@
|
||||
%h1 Editing District
|
||||
= render 'form', district: @district
|
||||
= link_to 'Show', @district
|
||||
|
|
||||
= link_to 'Back', districts_path
|
||||
@ -1,4 +0,0 @@
|
||||
json.array!(@districts) do |district|
|
||||
json.extract! district, :id, :name, :state_id
|
||||
json.url district_url(district, format: :json)
|
||||
end
|
||||
@ -1,3 +0,0 @@
|
||||
%h1 New District
|
||||
= render 'form', district: @district
|
||||
= link_to 'Back', districts_path
|
||||
@ -1,35 +0,0 @@
|
||||
- if user_signed_in? && current_user.super_admin?
|
||||
.row.super-admin
|
||||
.col-12
|
||||
%p= link_to "Create A New School In This District", new_legacy_district_legacy_school_path(@district)
|
||||
|
||||
|
||||
- if true || user_signed_in?
|
||||
.row.mt-3
|
||||
.col-3
|
||||
.district-logo= image_tag("#{@district.name.downcase}.png", class: 'img-fluid')
|
||||
|
||||
.col-6.offset-1
|
||||
%br
|
||||
%br
|
||||
%h4
|
||||
Schools in
|
||||
= @district.name
|
||||
|
||||
%br
|
||||
- @schools.each do |school|
|
||||
- next if ["dorchester-academy", "william-mckinley-school", "edco-youth"].index(school.slug)
|
||||
%p= link_to school.name, school
|
||||
|
||||
%br
|
||||
%br
|
||||
%br
|
||||
%br
|
||||
= link_to "View All Districts", root_path
|
||||
|
||||
- else
|
||||
.text-center.my-3.py-3
|
||||
%h3.my-3.py-3
|
||||
MCIEA is currently in beta testing.
|
||||
%p.py-3
|
||||
If you have an account, please sign in.
|
||||
@ -1 +0,0 @@
|
||||
json.extract! @district, :id, :name, :state_id, :created_at, :updated_at
|
||||
@ -1,22 +0,0 @@
|
||||
= form_for(question_list, as: 'question_list') do |f|
|
||||
- if question_list.errors.any?
|
||||
#error_explanation
|
||||
%h2
|
||||
= pluralize(question_list.errors.count, "error")
|
||||
prohibited this question_list from being saved:
|
||||
%ul
|
||||
- question_list.errors.full_messages.each do |message|
|
||||
%li= message
|
||||
.form-group
|
||||
= f.label :name
|
||||
= f.text_field :name, class: 'form-control'
|
||||
.form-group
|
||||
= f.label :description
|
||||
= f.text_area :description, class: 'form-control'
|
||||
.form-group
|
||||
= f.label :question_id_array, 'Questions'
|
||||
%br/
|
||||
.form-check.form-check-collection
|
||||
= f.collection_check_boxes(:question_id_array, Legacy::Question.all, :id, :text) { |c| c.label(class: 'form-check-label') { c.check_box(class: 'form-check-input') + " #{c.text}" } }
|
||||
.form-group
|
||||
= f.submit 'Save List', class: 'btn btn-primary'
|
||||
@ -1,5 +0,0 @@
|
||||
%h1 Editing Question List
|
||||
= render 'form', question_list: @question_list
|
||||
= link_to 'Show', @question_list
|
||||
|
|
||||
= link_to 'Back', legacy_question_lists_path
|
||||
@ -1,20 +0,0 @@
|
||||
%p#notice= notice
|
||||
%h1 Question Lists
|
||||
%table
|
||||
%thead
|
||||
%tr
|
||||
%th Name
|
||||
%th Description
|
||||
%th Question ids
|
||||
%th{:colspan => "3"}
|
||||
%tbody
|
||||
- @question_lists.each do |question_list|
|
||||
%tr
|
||||
%td= question_list.name
|
||||
%td= question_list.description
|
||||
%td= question_list.question_ids
|
||||
%td= link_to 'Show', question_list
|
||||
%td= link_to 'Edit', edit_legacy_question_list_path(question_list)
|
||||
%td= link_to 'Destroy', question_list, method: :delete, data: { confirm: 'Are you sure?' }
|
||||
%br/
|
||||
= link_to 'New Question List', new_legacy_question_list_path
|
||||
@ -1,4 +0,0 @@
|
||||
json.array!(@question_lists) do |question_list|
|
||||
json.extract! question_list, :id, :name, :description, :question_ids
|
||||
json.url question_list_url(question_list, format: :json)
|
||||
end
|
||||
@ -1,6 +0,0 @@
|
||||
.row
|
||||
.offset-sm-2.col-sm-8
|
||||
%h3 Create A Question List
|
||||
= render 'form', question_list: @question_list
|
||||
%br
|
||||
%p= link_to 'Back', root_path
|
||||
@ -1,20 +0,0 @@
|
||||
%p#notice= notice
|
||||
%p
|
||||
%strong Name:
|
||||
= @question_list.name
|
||||
%p
|
||||
%strong Description:
|
||||
= @question_list.description
|
||||
|
||||
%p
|
||||
= link_to 'Edit', edit_legacy_question_list_path(@question_list)
|
||||
|
|
||||
= link_to 'Back', legacy_question_lists_path
|
||||
|
||||
%br
|
||||
%br
|
||||
|
||||
%p
|
||||
%strong Questions:
|
||||
- @question_list.questions.each do |question|
|
||||
%p= link_to question.text, question
|
||||
@ -1 +0,0 @@
|
||||
json.extract! @question_list, :id, :name, :description, :question_ids, :created_at, :updated_at
|
||||
@ -1,32 +0,0 @@
|
||||
= form_for(question, as: 'question') do |f|
|
||||
- if question.errors.any?
|
||||
#error_explanation
|
||||
%h2
|
||||
= pluralize(question.errors.count, "error")
|
||||
prohibited this question from being saved:
|
||||
%ul
|
||||
- question.errors.full_messages.each do |message|
|
||||
%li= message
|
||||
.field
|
||||
= f.label :text
|
||||
= f.text_field :text
|
||||
.field
|
||||
= f.label :option1
|
||||
= f.text_field :option1
|
||||
.field
|
||||
= f.label :option2
|
||||
= f.text_field :option2
|
||||
.field
|
||||
= f.label :option3
|
||||
= f.text_field :option3
|
||||
.field
|
||||
= f.label :option4
|
||||
= f.text_field :option4
|
||||
.field
|
||||
= f.label :option5
|
||||
= f.text_field :option5
|
||||
.field
|
||||
= f.label :category_id
|
||||
= f.number_field :category_id
|
||||
.actions
|
||||
= f.submit
|
||||
@ -1,58 +0,0 @@
|
||||
- aggregated_responses = question.aggregated_responses_for_school(@school)
|
||||
- return if aggregated_responses.nil?
|
||||
- school_question = Legacy::SchoolQuestion.for(@school, question).first
|
||||
- valid_responses = school_question.nil? ? true : school_question.response_rate > 0.3 # || (aggregated_responses.count.to_f / @school.available_responders_for(question).to_f)) >= 0.3
|
||||
|
||||
.col-12.col-md-6.py-3
|
||||
.question.p-2{id: "question-#{question.id}"}
|
||||
%p.question-text.pt-3.px-2
|
||||
= question.normalized_text
|
||||
|
||||
- if valid_responses
|
||||
.row.pt-2
|
||||
.col-4.indicator-container.centered
|
||||
= render 'legacy/school_categories/indicator', info: aggregated_responses, small: true
|
||||
|
||||
.col-8
|
||||
%p
|
||||
%b Total Responses:
|
||||
= aggregated_responses.count
|
||||
%p
|
||||
%b Most Popular:
|
||||
= truncate(aggregated_responses.most_popular_answer, length: 27)
|
||||
%p
|
||||
%b Source:
|
||||
= question.source.titleize
|
||||
- else
|
||||
.row.pt-2
|
||||
.col-12.centered
|
||||
.px-2
|
||||
%br
|
||||
%h5 Insufficient Responses
|
||||
%p No data is displayed for this question because of insufficient responses.
|
||||
- if params.include?(:show_possible)
|
||||
%p= "Responded: #{aggregated_responses.count}, Possible: #{@school.available_responders_for(question)}"
|
||||
%p= "Source: #{question.for_teachers? ? "Teachers" : "Students"}"
|
||||
%br
|
||||
|
||||
|
||||
- if valid_responses
|
||||
.clearfix
|
||||
|
||||
.show-hide.px-2
|
||||
%p
|
||||
%a{"aria-controls" => "histogram#{question.id}", "aria-expanded" => "false", "data-toggle" => "collapse", :href => "#histogram#{question.id}"}
|
||||
Histogram
|
||||
|
|
||||
%a{"aria-controls" => "raw-data#{question.id}", "aria-expanded" => "false", "data-toggle" => "collapse", :href => "#raw-data#{question.id}"}
|
||||
Raw Data
|
||||
|
||||
.collapse{id: "histogram#{question.id}"}
|
||||
= render 'legacy/shared/histogram', data: aggregated_responses
|
||||
|
||||
%p.collapse{id: "raw-data#{question.id}"}
|
||||
= aggregated_responses.responses.map(&:answer_index_with_reverse).join(', ')
|
||||
|
||||
-# - if school_question.present?
|
||||
-# .clearfix
|
||||
-# %p= "Attempts: #{school_question.attempt_count}, Responses: #{school_question.response_count}, Response Rate: #{number_to_percentage(school_question.response_rate * 100, precision: 0)}, Total: #{school_question.response_total}"
|
||||
@ -1,5 +0,0 @@
|
||||
%h1 Editing Question
|
||||
= render 'form', question: @question
|
||||
= link_to 'Show', @question
|
||||
|
|
||||
= link_to 'Back', legacy_questions_path
|
||||
@ -1,28 +0,0 @@
|
||||
%p#notice= notice
|
||||
%h1 Questions
|
||||
%table
|
||||
%thead
|
||||
%tr
|
||||
%th Text
|
||||
%th Option1
|
||||
%th Option2
|
||||
%th Option3
|
||||
%th Option4
|
||||
%th Option5
|
||||
%th Category
|
||||
%th{:colspan => "3"}
|
||||
%tbody
|
||||
- @questions.each do |question|
|
||||
%tr
|
||||
%td= question.text
|
||||
%td= question.option1
|
||||
%td= question.option2
|
||||
%td= question.option3
|
||||
%td= question.option4
|
||||
%td= question.option5
|
||||
%td= link_to(question.category.name, question.category)
|
||||
%td= link_to 'Show', question
|
||||
%td= link_to 'Edit', edit_legacy_question_path(question)
|
||||
%td= link_to 'Destroy', question, method: :delete, data: { confirm: 'Are you sure?' }
|
||||
%br/
|
||||
= link_to 'New Question', new_legacy_question_path
|
||||
@ -1,4 +0,0 @@
|
||||
json.array!(@questions) do |question|
|
||||
json.extract! question, :id, :text, :option1, :option2, :option3, :option4, :option5, :category_id
|
||||
json.url question_url(question, format: :json)
|
||||
end
|
||||
@ -1,3 +0,0 @@
|
||||
%h1 New Question
|
||||
= render 'form', question: @question
|
||||
= link_to 'Back', legacy_questions_path
|
||||
@ -1,39 +0,0 @@
|
||||
%p#notice= notice
|
||||
%p
|
||||
%strong Text:
|
||||
= @question.text
|
||||
%p
|
||||
%strong Option1:
|
||||
= @question.option1
|
||||
%p
|
||||
%strong Option2:
|
||||
= @question.option2
|
||||
%p
|
||||
%strong Option3:
|
||||
= @question.option3
|
||||
%p
|
||||
%strong Option4:
|
||||
= @question.option4
|
||||
%p
|
||||
%strong Option5:
|
||||
= @question.option5
|
||||
%p
|
||||
%strong Category:
|
||||
|
||||
- if @question.category.present?
|
||||
= render partial: 'legacy/categories/full_path', locals: {category: @question.category}
|
||||
- else
|
||||
No Category
|
||||
|
||||
= link_to 'Edit', edit_legacy_question_path(@question)
|
||||
|
|
||||
= link_to 'Back', legacy_questions_path
|
||||
|
||||
|
||||
%br
|
||||
%br
|
||||
%br
|
||||
%h4
|
||||
Results For
|
||||
= @school.name
|
||||
= render @question
|
||||
@ -1,2 +0,0 @@
|
||||
json.extract! @question, :id, :text, :option1, :option2, :option3, :option4, :option5, :category_id, :created_at,
|
||||
:updated_at
|
||||
@ -1,24 +0,0 @@
|
||||
= form_for([@school, @recipient_list], as: 'recipient_list') do |f|
|
||||
- if @recipient_list.errors.any?
|
||||
#error_explanation
|
||||
%h2
|
||||
= pluralize(@recipient_list.errors.count, "error")
|
||||
prohibited this recipient_list from being saved:
|
||||
%ul
|
||||
- @recipient_list.errors.full_messages.each do |msg|
|
||||
%li= msg
|
||||
.form-group
|
||||
= f.label :name
|
||||
%br/
|
||||
= f.text_field :name, class: 'form-control'
|
||||
.form-group
|
||||
= f.label :description
|
||||
%br/
|
||||
= f.text_area :description, class: 'form-control'
|
||||
.form-group
|
||||
= f.label :recipient_id_array, 'Recipients'
|
||||
%br/
|
||||
.form-check.form-check-collection
|
||||
= f.collection_check_boxes(:recipient_id_array, @school.recipients.all, :id, :name) { |c| c.label(class: 'form-check-label') { c.check_box(class: 'form-check-input') + " #{c.text}" } }
|
||||
.form-group
|
||||
= f.submit 'Save List', class: 'btn btn-primary'
|
||||
@ -1,7 +0,0 @@
|
||||
.row
|
||||
.offset-sm-2.col-sm-8
|
||||
%h3 Edit Recipient List
|
||||
= render 'form'
|
||||
%br
|
||||
%p= link_to 'Show', [@recipient_list.school, @recipient_list]
|
||||
%p= link_to 'Back',@school
|
||||
@ -1,19 +0,0 @@
|
||||
%h1 Listing recipient_lists
|
||||
%table
|
||||
%tr
|
||||
%th Name
|
||||
%th Description
|
||||
%th Recipient ids
|
||||
%th
|
||||
%th
|
||||
%th
|
||||
- @recipient_lists.each do |recipient_list|
|
||||
%tr
|
||||
%td= recipient_list.name
|
||||
%td= recipient_list.description
|
||||
%td= recipient_list.recipient_ids
|
||||
%td= link_to 'Show', [recipient_list.school, recipient_list]
|
||||
%td= link_to 'Edit', edit_legacy_school_legacy_recipient_list_path(recipient_list.school, recipient_list)
|
||||
%td= link_to 'Destroy', [recipient_list.school, recipient_list], :confirm => 'Are you sure?', :method => :delete
|
||||
%br/
|
||||
= link_to 'New Recipient list', new_legacy_school_legacy_recipient_list_path(@school)
|
||||
@ -1,6 +0,0 @@
|
||||
.row
|
||||
.offset-sm-2.col-sm-8
|
||||
%h3 Create A Recipient List For This School
|
||||
= render 'form', recipient_list: @recipient_list
|
||||
%br
|
||||
%p= link_to 'Back', @school
|
||||
@ -1,22 +0,0 @@
|
||||
%p
|
||||
%b School:
|
||||
= link_to @school.name, legacy_school_admin_path(@school)
|
||||
%p
|
||||
%b Name:
|
||||
= @recipient_list.name
|
||||
%p
|
||||
%b Description:
|
||||
= @recipient_list.description
|
||||
|
||||
%p
|
||||
= link_to 'Edit', edit_legacy_school_legacy_recipient_list_path(@recipient_list.school, @recipient_list)
|
||||
|
|
||||
= link_to 'Back', @recipient_list.school
|
||||
|
||||
%br
|
||||
%br
|
||||
|
||||
%p
|
||||
%b Recipients:
|
||||
- @recipient_list.recipients.each do |recipient|
|
||||
%p= link_to recipient.name, [@school, recipient]
|
||||
@ -1,38 +0,0 @@
|
||||
= form_for([@school, recipient], as: 'recipient') do |f|
|
||||
- if recipient.errors.any?
|
||||
#error_explanation
|
||||
%h2
|
||||
= pluralize(recipient.errors.count, "error")
|
||||
prohibited this recipient from being saved:
|
||||
%ul
|
||||
- recipient.errors.full_messages.each do |message|
|
||||
%li= message
|
||||
.form-group
|
||||
= f.label :name
|
||||
= f.text_field :name, class: 'form-control'
|
||||
.form-group
|
||||
= f.label :phone
|
||||
= f.text_field :phone, class: 'form-control'
|
||||
.form-group
|
||||
= f.label :birth_date
|
||||
= f.date_select :birth_date, class: 'form-control'
|
||||
.form-group
|
||||
= f.label :gender
|
||||
= f.text_field :gender, class: 'form-control'
|
||||
.form-group
|
||||
= f.label :race
|
||||
= f.text_field :race, class: 'form-control'
|
||||
.form-group
|
||||
= f.label :ethnicity
|
||||
= f.text_field :ethnicity, class: 'form-control'
|
||||
.form-group
|
||||
= f.label :home_language_id
|
||||
= f.number_field :home_language_id, class: 'form-control'
|
||||
.form-group
|
||||
= f.label :income
|
||||
= f.text_field :income, class: 'form-control'
|
||||
-# .form-group
|
||||
-# = f.label :school_id
|
||||
-# = f.number_field :school_id
|
||||
.actions
|
||||
= f.submit 'Save', class: 'btn btn-primary'
|
||||
@ -1,5 +0,0 @@
|
||||
%h1 Editing Recipient
|
||||
= render 'form', recipient: @recipient
|
||||
= link_to 'Show', legacy_school_legacy_recipient_path(@school, @recipient)
|
||||
|
|
||||
= link_to 'Back', legacy_school_path(@school)
|
||||
@ -1,9 +0,0 @@
|
||||
.row
|
||||
.offset-sm-2.col-sm-8
|
||||
%h3 Import Recipients To This School
|
||||
= form_tag import_legacy_school_legacy_recipients_path(@school), multipart: true do
|
||||
%br
|
||||
.form-group
|
||||
= file_field_tag :file, class: 'form-control-file'
|
||||
.form-group
|
||||
= submit_tag "Import", class: 'btn btn-primary'
|
||||
@ -1,33 +0,0 @@
|
||||
%h1 Recipients
|
||||
%table
|
||||
%thead
|
||||
%tr
|
||||
%th Name
|
||||
%th Phone
|
||||
%th Birth date
|
||||
%th Gender
|
||||
%th Race
|
||||
%th Ethnicity
|
||||
%th Home language
|
||||
%th Income
|
||||
%th Opted out
|
||||
%th School
|
||||
%th{:colspan => "3"}
|
||||
%tbody
|
||||
- @recipients.each do |recipient|
|
||||
%tr
|
||||
%td= recipient.name
|
||||
%td= recipient.phone
|
||||
%td= recipient.birth_date
|
||||
%td= recipient.gender
|
||||
%td= recipient.race
|
||||
%td= recipient.ethnicity
|
||||
%td= recipient.home_language_id
|
||||
%td= recipient.income
|
||||
%td= recipient.opted_out
|
||||
%td= recipient.school_id
|
||||
%td= link_to 'Show', legacy_school_legacy_recipient_path(@school, recipient)
|
||||
%td= link_to 'Edit', edit_legacy_school_legacy_recipient_path(@school, recipient)
|
||||
%td= link_to 'Destroy', legacy_school_legacy_recipient_path(@school, recipient), method: :delete, data: { confirm: 'Are you sure?' }
|
||||
%br/
|
||||
= link_to 'New Recipient', new_legacy_school_legacy_recipient_path(@school)
|
||||
@ -1,5 +0,0 @@
|
||||
json.array!(@recipients) do |recipient|
|
||||
json.extract! recipient, :id, :name, :phone, :birth_date, :gender, :race, :ethnicity, :home_language_id, :income,
|
||||
:opted_out, :school_id
|
||||
json.url recipient_url(recipient, format: :json)
|
||||
end
|
||||
@ -1,6 +0,0 @@
|
||||
.row
|
||||
.offset-sm-2.col-sm-8
|
||||
%h3 Add A Recipient To This School
|
||||
= render 'form', recipient: @recipient
|
||||
%br
|
||||
%p= link_to 'Back', @school
|
||||
@ -1,78 +0,0 @@
|
||||
.row
|
||||
.col
|
||||
%p
|
||||
%strong School:
|
||||
= link_to @school.name, legacy_school_admin_path(@school)
|
||||
%p
|
||||
%strong Recipient:
|
||||
= @recipient.name
|
||||
|
||||
- if @recipient.phone.present?
|
||||
%p
|
||||
%strong Phone:
|
||||
= @recipient.phone
|
||||
|
||||
- if @recipient.birth_date.present?
|
||||
%p
|
||||
%strong Birth date:
|
||||
= @recipient.birth_date
|
||||
|
||||
- if @recipient.gender.present?
|
||||
%p
|
||||
%strong Gender:
|
||||
= @recipient.gender
|
||||
|
||||
- if @recipient.race.present?
|
||||
%p
|
||||
%strong Race:
|
||||
= @recipient.race
|
||||
|
||||
- if @recipient.ethnicity.present?
|
||||
%p
|
||||
%strong Ethnicity:
|
||||
= @recipient.ethnicity
|
||||
|
||||
- if @recipient.home_language_id.present?
|
||||
%p
|
||||
%strong Home language:
|
||||
= @recipient.home_language_id
|
||||
|
||||
- if @recipient.income.present?
|
||||
%p
|
||||
%strong Income:
|
||||
= @recipient.income
|
||||
|
||||
%p
|
||||
%strong Opted out:
|
||||
= @recipient.opted_out
|
||||
|
||||
- if (recipient_schedule = @recipient.recipient_schedules.first).present?
|
||||
%p
|
||||
%strong Last Attempt At:
|
||||
= recipient_schedule.last_attempt_at.in_time_zone('Eastern Time (US & Canada)').strftime('%m-%e-%y %H:%M')
|
||||
|
||||
%p
|
||||
%strong Next Attempt At:
|
||||
= recipient_schedule.next_attempt_at.in_time_zone('Eastern Time (US & Canada)').strftime('%m-%e-%y %H:%M')
|
||||
|
||||
= link_to 'Edit', edit_legacy_school_legacy_recipient_path(@school, @recipient)
|
||||
|
|
||||
= link_to 'Back', legacy_school_path(@school)
|
||||
|
||||
|
||||
%br
|
||||
%br
|
||||
%br
|
||||
%h4 Attempts
|
||||
%table{style: 'width: 100%;'}
|
||||
%tbody
|
||||
%thead{style: 'font-weight: bold;'}
|
||||
%th Date
|
||||
%th Question
|
||||
%th Response
|
||||
- @recipient.attempts.each do |attempt|
|
||||
%tr.attempt
|
||||
%td
|
||||
= attempt.sent_at.strftime('%x') if attempt.sent_at.present?
|
||||
%td= link_to truncate(attempt.question.text, length: 60), [@school, attempt.question], title: attempt.question.text
|
||||
%td= "(#{attempt.answer_index_with_reverse}) #{attempt.response}"
|
||||
@ -1,2 +0,0 @@
|
||||
json.extract! @recipient, :id, :name, :phone, :birth_date, :gender, :race, :ethnicity, :home_language_id, :income,
|
||||
:opted_out, :school_id, :created_at, :updated_at
|
||||
@ -1,51 +0,0 @@
|
||||
= form_for([@schedule.school, @schedule], as: 'schedule') do |f|
|
||||
- if @schedule.errors.any?
|
||||
#error_explanation
|
||||
%h2
|
||||
= pluralize(@schedule.errors.count, "error")
|
||||
prohibited this schedule from being saved:
|
||||
%ul
|
||||
- @schedule.errors.full_messages.each do |msg|
|
||||
%li= msg
|
||||
.form-group
|
||||
= f.label :name
|
||||
%br/
|
||||
= f.text_field :name, class: 'form-control'
|
||||
.form-group
|
||||
= f.label :description
|
||||
%br/
|
||||
= f.text_area :description, class: 'form-control'
|
||||
.form-group
|
||||
= f.label :frequency_hours, 'How often should be people be surveyed?'
|
||||
%br/
|
||||
= f.select :frequency_hours, options_for_frequency_hours, class: 'form-control'
|
||||
.form-group
|
||||
= f.label :start_date
|
||||
%br/
|
||||
= f.date_select :start_date, class: 'form-control'
|
||||
.form-group
|
||||
= f.label :end_date
|
||||
%br/
|
||||
= f.date_select :end_date, class: 'form-control'
|
||||
.form-group
|
||||
= f.label :time, 'Time of Day (what time should people receive the text)'
|
||||
%br/
|
||||
= f.select :time, options_for_time, class: 'form-control'
|
||||
.form-group
|
||||
= f.label :active
|
||||
%br/
|
||||
= f.check_box :active, class: 'form-control'
|
||||
.form-group
|
||||
= f.label :random
|
||||
%br/
|
||||
= f.check_box :random, class: 'form-control'
|
||||
.form-group
|
||||
= f.label :recipient_list_id
|
||||
%br/
|
||||
= f.collection_select :recipient_list_id, @school.recipient_lists.all, :id, :name, class: 'form-control'
|
||||
.form-group
|
||||
= f.label :question_list_id
|
||||
%br/
|
||||
= f.collection_select :question_list_id, Legacy::QuestionList.all, :id, :name, class: 'form-control'
|
||||
.form-group
|
||||
= f.submit 'Save Schedule', class: 'btn btn-primary'
|
||||
@ -1,5 +0,0 @@
|
||||
%h1 Editing schedule
|
||||
= render 'form'
|
||||
= link_to 'Show', [@schedule.school, @schedule]
|
||||
|
|
||||
= link_to 'Back', legacy_school_legacy_schedules_path(@schedule.school)
|
||||
@ -1,6 +0,0 @@
|
||||
.row
|
||||
.offset-2.col-8
|
||||
%h3 Create A New Schedule For This School
|
||||
= render 'form', schedule: @schedule
|
||||
%br
|
||||
%p= link_to 'Back', @school
|
||||
@ -1,35 +0,0 @@
|
||||
%p#notice= notice
|
||||
%p
|
||||
%b Name:
|
||||
= @schedule.name
|
||||
%p
|
||||
%b Description:
|
||||
= @schedule.description
|
||||
%p
|
||||
%b School:
|
||||
= link_to(@school.name, legacy_school_admin_path(@school))
|
||||
%p
|
||||
%b Frequency hours:
|
||||
= frequency_description(@schedule.frequency_hours)
|
||||
%p
|
||||
%b Start date:
|
||||
= @schedule.start_date
|
||||
%p
|
||||
%b End date:
|
||||
= @schedule.end_date
|
||||
%p
|
||||
%b Active:
|
||||
= @schedule.active
|
||||
%p
|
||||
%b Random:
|
||||
= @schedule.random
|
||||
%p
|
||||
%b Recipient list:
|
||||
= link_to(@schedule.recipient_list.name, [@school, @schedule.recipient_list])
|
||||
%p
|
||||
%b Question list:
|
||||
= link_to(@schedule.question_list.name, @schedule.question_list)
|
||||
|
||||
= link_to 'Edit', edit_legacy_school_legacy_schedule_path(@schedule.school, @schedule)
|
||||
|
|
||||
= link_to 'Back', legacy_school_legacy_schedules_path(@schedule.school)
|
||||
@ -1,4 +0,0 @@
|
||||
json.array!(@school_recipient_lists) do |school_recipient_list|
|
||||
json.extract! school_recipient_list, :id, :name, :description, :recipient_ids
|
||||
json.url legacy_school_legacy_recipient_list_url(school_recipient_list, format: :json)
|
||||
end
|
||||
@ -1 +0,0 @@
|
||||
json.extract! @school_recipient_list, :id, :name, :description, :recipient_ids, :created_at, :updated_at
|
||||
@ -1,5 +0,0 @@
|
||||
json.array!(@school_schedules) do |school_schedule|
|
||||
json.extract! school_schedule, :id, :name, :description, :school_id, :frequency_hours, :start_date, :end_date,
|
||||
:active, :random, :recipient_list_id, :question_list_id
|
||||
json.url school_schedule_url(school_schedule, format: :json)
|
||||
end
|
||||
@ -1,2 +0,0 @@
|
||||
json.extract! @school_schedule, :id, :name, :description, :school_id, :frequency_hours, :start_date, :end_date,
|
||||
:active, :random, :recipient_list_id, :question_list_id, :created_at, :updated_at
|
||||
@ -1,48 +0,0 @@
|
||||
- return if info.nil?
|
||||
- likert = info.answer_index_average
|
||||
- zscore = info.zscore.present? ? info.zscore + 3 : nil
|
||||
- likert = zscore if zscore.present?
|
||||
- likert = likert.round(1)
|
||||
|
||||
- return if likert.nan?
|
||||
|
||||
- num_likerts = 5
|
||||
- average_offset = (likert/num_likerts) * 100
|
||||
|
||||
- default_approval_zone = [[76, 90], [77, 91], [71, 85], [73, 86], [73, 86], []][info.category.root_index]
|
||||
|
||||
- zone_descriptions = ['Warning Zone: Schools that fall in this range are five or more years away from reaching community-wide targets. Consequently, this zone, as established by teachers, principals, parents, and district administrators, indicates that a school is in significant need of improvement. If the school is not in the Warning Zone in other areas, it may be a relatively successful school overall. Still, it must immediately develop a plan for addressing its shortcomings.', 'Watch Zone: Schools falling in this range are three or four years away from reaching community-wide targets. This zone, established by teachers, principals, parents, and district administrators, is not an ideal place for schools to be. But it does not mean that the school is failing. Instead, it means that the school needs to place particular emphasis on improving its work in this area.', 'Growth Zone: Schools falling in this range earned scores just below "acceptable." Yet these schools are close enough to the Approval Zone that they might reasonably reach it within two years. As established by teachers, principals, parents, and district administrators, this zone is an acceptable place for schools to be if they have the leadership, focus, and resources to improve their work in a particular area.', 'Approval Zone: Schools falling in this range earned scores between "acceptable" and "ideal." This zone, established by teachers, principals, parents, and district administrators, is the target that all schools should be striving to hit. Scoring in this range does not mean that a school is perfect; but it does mean that it is meeting or exceeding community-wide expectations in a particular category.', 'This area represents a set of outcomes so close to perfect that they are unlikely to be realized in any school.']
|
||||
|
||||
- if (zone_widths = info.category.zone_widths).nil?
|
||||
- if default_approval_zone.present?
|
||||
- zone_widths = [default_approval_zone[0] - (15 + 15)]
|
||||
- zone_widths << 15
|
||||
- zone_widths << 15
|
||||
- zone_widths << default_approval_zone[1] - default_approval_zone[0]
|
||||
- zone_widths << 100 - default_approval_zone[1]
|
||||
- zone_widths = zone_widths.map { |z| z / 20.0 }
|
||||
- else
|
||||
- zone_widths = [5]
|
||||
- zone_descriptions = ['There is not yet any national data to compare to for this measure.']
|
||||
|
||||
- buffer = 0.25
|
||||
- this_school_zone = "This school scored in the range between #{(likert - buffer).round(2)} and #{(likert + buffer).round(2)}.\n\nMouse over each color to read a description of each zone."
|
||||
|
||||
.indicator{class: (local_assigns[:small] ? 'small' : '')}
|
||||
.indicator-circle
|
||||
.indicator-zones{style: "margin-left: #{local_assigns[:small] ? ((average_offset - 5) * -10) : 0}%"}
|
||||
- zone_total = 0
|
||||
- zone_descriptions.each_with_index do |zone, index|
|
||||
%div{class: "zone#{index}", style: "width: #{zone_widths[index]*20}%", title: "#{zone}\n\nThis zone: #{(zone_total).round(2)} - #{((zone_total + zone_widths[index])).round(2)}\nThis school: #{(likert - buffer).round(2)} - #{(likert + buffer).round(2)}"}
|
||||
- zone_total += zone_widths[index]
|
||||
- if local_assigns[:small]
|
||||
-#
|
||||
.average{title: this_school_zone}
|
||||
This School
|
||||
- else
|
||||
.average{style: "left: #{average_offset - 5}%", title: this_school_zone}
|
||||
%span= "This School #{likert}"
|
||||
|
||||
- if local_assigns[:caption]
|
||||
.explanation
|
||||
* Mouse-over each colored area for detailed description.
|
||||
@ -1,24 +0,0 @@
|
||||
.col-12.col-sm-6.py-3
|
||||
.school_category.short.p-2
|
||||
%h4.title.text-center.pt-3
|
||||
= link_to(school_category.category.name, legacy_school_legacy_category_path(school_category.school, school_category.category, year: school_category.year))
|
||||
|
||||
- if !school_category.new_record? && (school_category.school.district.name != "Boston" || (school_category.valid_child_count || 1) > 0)
|
||||
.indicator-container.short
|
||||
= render 'legacy/school_categories/indicator', info: school_category
|
||||
|
||||
.description.px-2.pt-3.pb-2.mt-2
|
||||
- if false #(measurements = school_category.questions.measurements.for_school(school_measure.school)).present?
|
||||
= render 'measurements/nonlikert', measurement: measurements.first, description: school_measure.measure.description
|
||||
- else
|
||||
= school_category.category.blurb || truncate(school_category.category.description, length: 108)
|
||||
|
||||
- else
|
||||
.row.py-1
|
||||
.col-12.centered
|
||||
.px-2
|
||||
%h5 Insufficient Responses
|
||||
%p No data is displayed for this measure because of insufficient responses.
|
||||
%br
|
||||
%br
|
||||
%br
|
||||
@ -1,17 +0,0 @@
|
||||
= form_for(school, as: 'school') do |f|
|
||||
- if school.errors.any?
|
||||
#error_explanation
|
||||
%h2
|
||||
= pluralize(school.errors.count, "error")
|
||||
prohibited this school from being saved:
|
||||
%ul
|
||||
- school.errors.full_messages.each do |message|
|
||||
%li= message
|
||||
.form-group
|
||||
= f.label :name
|
||||
= f.text_field :name, class: 'form-control'
|
||||
-# .form-group
|
||||
-# = f.label :district_id
|
||||
-# = f.number_field :district_id, class: 'form-control'
|
||||
.form-group
|
||||
= f.submit 'Save School', class: 'btn btn-primary'
|
||||
@ -1,129 +0,0 @@
|
||||
.row
|
||||
.col
|
||||
%p
|
||||
%strong Name:
|
||||
= @school.name
|
||||
%p
|
||||
%strong District:
|
||||
= @school.district_id
|
||||
|
||||
%p= link_to "Add Recipient", new_legacy_school_legacy_recipient_path(@school)
|
||||
|
||||
%p= link_to "Bulk Add Recipients", import_legacy_school_legacy_recipients_path(@school)
|
||||
|
||||
%p= link_to "Create Recipient List", new_legacy_school_legacy_recipient_list_path(@school)
|
||||
|
||||
%p= link_to "Create A Question List", new_legacy_question_list_path()
|
||||
|
||||
%p= link_to "Create A Schedule", new_legacy_school_legacy_schedule_path(@school)
|
||||
|
||||
= link_to 'Edit', edit_legacy_school_path(@school)
|
||||
|
|
||||
= link_to 'Back', root_path
|
||||
|
||||
|
||||
%br
|
||||
%br
|
||||
%br
|
||||
%h4
|
||||
School Schedules
|
||||
%small
|
||||
= link_to('show/hide', '#school_schedules', data: {toggle: 'collapse'}, 'aria-expanded': 'false', 'aria-controls': 'collapseExample')
|
||||
#school_schedules.collapse.show
|
||||
- if @school.schedules.blank?
|
||||
%p
|
||||
%strong None Yet
|
||||
- else
|
||||
%table{style: 'width: 100%;'}
|
||||
%tbody
|
||||
%thead{style: 'font-weight: bold;'}
|
||||
%th Name
|
||||
%th Start
|
||||
%th End
|
||||
%th{colspan: 2} Actions
|
||||
- @school.schedules.each do |schedule|
|
||||
%tr.recipient
|
||||
%td= link_to schedule.name, [@school, schedule]
|
||||
%td= schedule.start_date
|
||||
%td= schedule.end_date
|
||||
%td= link_to('Edit', edit_legacy_school_legacy_schedule_path(@school, schedule))
|
||||
%td= link_to('Delete', legacy_school_legacy_schedule_path(@school, schedule), method: :delete, data: {confirm: 'Are you sure you want to delete this schedule?'})
|
||||
|
||||
%br
|
||||
%br
|
||||
%br
|
||||
%h4
|
||||
School Recipients Lists
|
||||
%small
|
||||
= link_to('show/hide', '#school_recipient_lists', data: {toggle: 'collapse'}, 'aria-expanded': 'false', 'aria-controls': 'collapseExample')
|
||||
#school_recipient_lists.collapse
|
||||
- if @school.recipient_lists.blank?
|
||||
%p
|
||||
%strong None Yet
|
||||
- else
|
||||
%table{style: 'width: 100%;'}
|
||||
%tbody
|
||||
%thead{style: 'font-weight: bold;'}
|
||||
%th Name
|
||||
%th Description
|
||||
%th{colspan: 2} Actions
|
||||
- @school.recipient_lists.each do |recipient_list|
|
||||
%tr.recipient
|
||||
%td= link_to recipient_list.name, [@school, recipient_list]
|
||||
%td= recipient_list.description
|
||||
%td= link_to('Edit', edit_legacy_school_legacy_recipient_list_path(@school, recipient_list))
|
||||
%td= link_to('Delete', legacy_school_legacy_recipient_list_path(@school, recipient_list), method: :delete, data: {confirm: 'Are you sure you want to delete this list?'})
|
||||
|
||||
%br
|
||||
%br
|
||||
%br
|
||||
%h4
|
||||
School Recipients
|
||||
%small
|
||||
= link_to('show/hide', '#school_recipients', data: {toggle: 'collapse'}, 'aria-expanded': 'false', 'aria-controls': 'collapseExample')
|
||||
#school_recipients.collapse
|
||||
- if @school.recipients.blank?
|
||||
%p
|
||||
%strong None Yet
|
||||
- else
|
||||
%table{style: 'width: 100%;'}
|
||||
%tbody
|
||||
%thead{style: 'font-weight: bold;'}
|
||||
%th Name
|
||||
%th Phone
|
||||
%th Attempts
|
||||
%th Responses
|
||||
%th{colspan: 2} Actions
|
||||
- @school.recipients.each do |recipient|
|
||||
%tr.recipient
|
||||
%td= link_to recipient.name, [@school, recipient]
|
||||
%td= recipient.phone
|
||||
%td= recipient.attempts_count
|
||||
%td= recipient.responses_count
|
||||
%td= link_to('Edit', edit_legacy_school_legacy_recipient_path(@school, recipient))
|
||||
%td= link_to('Delete', legacy_school_legacy_recipient_path(@school, recipient), method: :delete, data: {confirm: 'Are you sure you want to delete this recipient?'})
|
||||
|
||||
%br
|
||||
%br
|
||||
%br
|
||||
%h4
|
||||
Question Lists
|
||||
%small
|
||||
= link_to('show/hide', '#question_lists', data: {toggle: 'collapse'}, 'aria-expanded': 'false', 'aria-controls': 'collapseExample')
|
||||
#question_lists.collapse
|
||||
- if Legacy::QuestionList.count == 0
|
||||
%p
|
||||
%strong None Yet
|
||||
- else
|
||||
%table{style: 'width: 100%;'}
|
||||
%tbody
|
||||
%thead{style: 'font-weight: bold;'}
|
||||
%th Name
|
||||
%th Description
|
||||
%th{colspan: 2} Actions
|
||||
- Legacy::QuestionList.all.each do |question_list|
|
||||
%tr.question_list
|
||||
%td= link_to question_list.name, question_list
|
||||
%td= question_list.description
|
||||
%td= link_to('Edit', edit_legacy_question_list_path(question_list))
|
||||
%td= link_to('Delete', legacy_question_list_path(question_list), method: :delete, data: {confirm: 'Are you sure you want to delete this question list?'})
|
||||
@ -1,5 +0,0 @@
|
||||
%h1 Editing School
|
||||
= render 'form', school: @school
|
||||
= link_to 'Show', @school
|
||||
|
|
||||
= link_to 'Back', legacy_schools_path
|
||||
@ -1,6 +0,0 @@
|
||||
.row
|
||||
.offset-sm-2.col-sm-8
|
||||
%h3 Create A New School
|
||||
= render 'form', school: @school
|
||||
%br
|
||||
%p= link_to 'Back', legacy_schools_path
|
||||
@ -1,27 +0,0 @@
|
||||
= render 'layouts/legacy/school_header'
|
||||
|
||||
- if @school_categories.blank?
|
||||
.row.pt-3.mt-3
|
||||
|
||||
.row.pt-3.mt-3
|
||||
.col-12.text-center
|
||||
%h3 Insufficient Responses
|
||||
%p No data is displayed for this school because of insufficient responses.
|
||||
- elsif @district.name == "Boston"
|
||||
- sorted_categories = @school_categories.sort { |a, b| "#{a.category.path.first.name} #{a.category.name}" <=> "#{b.category.path.first.name} #{b.category.name}" }
|
||||
- grouped = sorted_categories.inject({}) do |hash, item|
|
||||
- all = hash[item.category.path.first] || []
|
||||
- all << item
|
||||
- hash[item.category.path.first] = all
|
||||
- hash
|
||||
- grouped.each do |root_category, group|
|
||||
.row.pt-3.mt-3
|
||||
.col-12
|
||||
%h3= root_category.name
|
||||
.row
|
||||
= render group
|
||||
- else
|
||||
.row
|
||||
= render @school_categories.sort { |a, b| a.root_index <=> b.root_index }
|
||||
|
||||
= render "legacy/shared/performance_spectrum"
|
||||
@ -1 +0,0 @@
|
||||
json.extract! @school, :id, :name, :district_id, :created_at, :updated_at
|
||||
@ -1,12 +0,0 @@
|
||||
- histogram = data.responses.map(&:answer_index_with_reverse).group_by { |a| a.to_s }
|
||||
%table.answers
|
||||
%tbody
|
||||
- data.question.options_with_reverse.each_with_index do |option, index|
|
||||
%tr.answer
|
||||
- group = histogram[(index + 1).to_s]
|
||||
- width = (100 * (group.blank? ? 0 : group.length)) / histogram.values.flatten.length
|
||||
%td.text
|
||||
= "#{option}:"
|
||||
= group.blank? ? 0 : group.length
|
||||
%td.count
|
||||
%div{class: "bar#{index}", style: "width: #{width}%"}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue