Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

E2416. Reimplement the Question hierarchy #83

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
de5fac9
Added uploadfile question type
vishwagandhi1610 Mar 14, 2024
c814847
added text_response question type
vishwagandhi1610 Mar 14, 2024
023044d
added textarea and textfield models and tests
vishwagandhi1610 Mar 14, 2024
536012f
Merge pull request #1 from vishwagandhi1610/dev
vishwagandhi1610 Mar 15, 2024
0a75f19
added question_advice.rb and criterion.rb model and criterion_rspec.rb
vishwagandhi1610 Mar 15, 2024
565ec85
Merge pull request #2 from vishwagandhi1610/dev
vishwagandhi1610 Mar 15, 2024
640154c
changed params
vishwagandhi1610 Mar 24, 2024
69cb47c
Merge pull request #4 from vishwagandhi1610/dev
vishwagandhi1610 Mar 24, 2024
6b978c1
added checkbox.rb and rspec tests
vishwagandhi1610 Apr 7, 2024
4379e55
Merge pull request #5 from vishwagandhi1610/dev
vishwagandhi1610 Apr 7, 2024
d0a8e73
added scale model and rspec tests
vishwagandhi1610 Apr 8, 2024
571443c
Merge pull request #6 from vishwagandhi1610/dev
vishwagandhi1610 Apr 8, 2024
26ae5f5
added dropdown model and rspec tests
vishwagandhi1610 Apr 8, 2024
1b5d9f0
Merge pull request #7 from vishwagandhi1610/dev
vishwagandhi1610 Apr 8, 2024
84286fd
added multiplechoice and rspec tests
vishwagandhi1610 Apr 9, 2024
1c765d1
Merge pull request #8 from vishwagandhi1610/dev
vishwagandhi1610 Apr 9, 2024
f8e7a6c
added multiplechoiceradio model and spec tests
vishwagandhi1610 Apr 9, 2024
fdacded
Merge pull request #9 from vishwagandhi1610/dev
vishwagandhi1610 Apr 9, 2024
88e6c22
comments and code updated
jaiwin3 Apr 9, 2024
84d5256
Revert "comments and code updated"
jaiwin3 Apr 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/controllers/api/v1/questions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def create
question = questionnaire.questions.build(
txt: params[:txt],
question_type: params[:question_type],
seq: params[:seq],
break_before: true
)

Expand Down
19 changes: 19 additions & 0 deletions app/helpers/question_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module QuestionHelper
def edit_common(label = nil,min_question_score = nil, max_question_score = nil, txt ,weight, type)
{
form: true,
label: label,
input_type: 'text',
input_name: 'question',
input_value: txt,
min_question_score: min_question_score,
max_question_score: max_question_score,
weight: weight,
type: type
}
end

def view_question_text_common(text, type, weight, score_range)
{ text: text, type: type, weight: weight, score_range: score_range }
end
end
172 changes: 172 additions & 0 deletions app/models/checkbox.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
class Checkbox < UnscoredQuestion
def edit(count)
{
remove_button: edit_remove_button(count),
seq: edit_seq(count),
question: edit_question(count),
type: edit_type(count),
weight: edit_weight(count)
}
end

def edit_remove_button(count)
{
type: 'remove_button',
action: 'delete',
href: "/questions/#{id}",
text: 'Remove'
}
end

def edit_seq(count)
{
type: 'seq',
input_size: 6,
value: seq,
name: "question[#{id}][seq]",
id: "question_#{id}_seq"
}
end

def edit_question(count)
{
type: 'textarea',
cols: 50,
rows: 1,
name: "question[#{id}][txt]",
id: "question_#{id}_txt",
placeholder: 'Edit question content here',
content: txt
}
end

def edit_type(count)
{
type: 'text',
input_size: 10,
disabled: true,
value: question_type,
name: "question[#{id}][type]",
id: "question_#{id}_type"
}
end

def edit_weight(count)
{
type: 'weight',
placeholder: 'UnscoredQuestion does not need weight'
}
end


def view_question_text
{
content: txt,
type: question_type,
weight: weight.to_s,
checked_state: 'Checked/Unchecked'
}
end

def complete(count, answer = nil)
{
previous_question: check_previous_question,
inputs: [
complete_first_second_input(count, answer),
complete_third_input(count, answer)
],
label: {
for: "responses_#{count}",
text: txt
},
script: complete_script(count),
if_column_header: complete_if_column_header
}
end

def check_previous_question
prev_question = Question.where('seq < ?', seq).order(:seq).last
{
type: prev_question&.type == 'ColumnHeader' ? 'ColumnHeader' : 'other'
}
end

def complete_first_second_input(count, answer = nil)
[
{
id: "responses_#{count}_comments",
name: "responses[#{count}][comment]",
type: 'hidden',
value: ''
},
{
id: "responses_#{count}_score",
name: "responses[#{count}][score]",
type: 'hidden',
value: answer&.answer == 1 ? '1' : '0'
}
]
end

def complete_third_input(count, answer = nil)
{
id: "responses_#{count}_checkbox",
type: 'checkbox',
onchange: "checkbox#{count}Changed()",
checked: answer&.answer == 1
}
end

def complete_script(count)
"function checkbox#{count}Changed() { var checkbox = jQuery('#responses_#{count}_checkbox'); var response_score = jQuery('#responses_#{count}_score'); if (checkbox.is(':checked')) { response_score.val('1'); } else { response_score.val('0'); }}"
end

def complete_if_column_header
next_question = Question.where('seq > ?', seq).order(:seq).first
if next_question
case next_question.question_type
when 'ColumnHeader'
'end_of_column_header'
when 'SectionHeader', 'TableHeader'
'end_of_section_or_table'
else
'continue'
end
else
'end'
end
end

def view_completed_question(count, answer)
{
previous_question: check_previous_question,
answer: view_completed_question_answer(count, answer),
if_column_header: view_completed_question_if_column_header
}
end

def view_completed_question_answer(count, answer)
{
number: count,
image: answer.answer == 1 ? 'Check-icon.png' : 'delete_icon.png',
content: txt,
bold: true
}
end

def view_completed_question_if_column_header
next_question = Question.where('seq > ?', seq).order(:seq).first
if next_question
case next_question.question_type
when 'ColumnHeader'
'end_of_column_header'
when 'TableHeader'
'end_of_table_header'
else
'continue'
end
else
'end'
end
end
end
81 changes: 81 additions & 0 deletions app/models/criterion.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
class Criterion < ScoredQuestion
validates :size, presence: true

def edit
{
remove_link: "/questions/#{id}",
sequence_input: seq.to_s,
question_text: txt,
question_type: question_type,
weight: weight.to_s,
size: size.to_s,
max_label: max_label,
min_label: min_label
}
end

def view_question_text
question_data = {
text: txt,
question_type: question_type,
weight: weight,
score_range: "#{questionnaire.min_question_score} to #{questionnaire.max_question_score}"
}

question_data[:score_range] = "(#{min_label}) " + question_data[:score_range] + " (#{max_label})" if max_label && min_label
question_data
end

def complete(count,answer = nil, questionnaire_min, questionnaire_max, dropdown_or_scale)
question_advices = QuestionAdvice.to_json_by_question_id(id)
advice_total_length = question_advices.sum { |advice| advice.advice.length unless advice.advice.blank? }

response_options = if dropdown_or_scale == 'dropdown'
dropdown_criterion_question(count, answer, questionnaire_min, questionnaire_max)
elsif dropdown_or_scale == 'scale'
scale_criterion_question(count, answer, questionnaire_min, questionnaire_max)
end

advice_section = question_advices.empty? || advice_total_length.zero? ? nil : advices_criterion_question(count, question_advices)

{
label: txt,
advice: advice_section,
response_options: response_options
}.compact # Use .compact to remove nil values
end

# Assuming now these methods should be public based on the test cases
def dropdown_criterion_question(count,answer, questionnaire_min, questionnaire_max)
options = (questionnaire_min..questionnaire_max).map do |score|
option = { value: score, label: score.to_s }
option[:selected] = 'selected' if answer && score == answer.answer
option
end
{ type: 'dropdown', options: options, current_answer: answer.try(:answer), comments: answer.try(:comments) }
end

def scale_criterion_question(count,answer, questionnaire_min, questionnaire_max)
{
type: 'scale',
min: questionnaire_min,
max: questionnaire_max,
current_answer: answer.try(:answer),
comments: answer.try(:comments),
min_label: min_label,
max_label: max_label,
size: size
}
end

private

def advices_criterion_question(question_advices)
question_advices.map do |advice|
{
score: advice.score,
advice: advice.advice
}
end
end
end
26 changes: 26 additions & 0 deletions app/models/dropdown.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
class Dropdown < UnscoredQuestion
include QuestionHelper

attr_accessor :txt, :type, :count, :weight
def edit(count)
edit_common("Question #{count}:", txt , weight, type).to_json
end

def view_question_text
view_question_text_common(txt, type, weight, 'N/A').to_json
end

def complete(count, answer = nil)
options = (1..count).map { |option| { value: option, selected: (option == answer.to_i) } }
{ dropdown_options: options }.to_json
end

def complete_for_alternatives(alternatives, answer)
options = alternatives.map { |alt| { value: alt, selected: (alt == answer) } }
{ dropdown_options: options }.to_json
end

def view_completed_question
{ selected_option: (count && answer) ? "#{answer} (out of #{count})" : 'Question not answered.' }.to_json
end
end
73 changes: 73 additions & 0 deletions app/models/multiple_choice_checkbox.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
require 'json'

class MultipleChoiceCheckbox < QuizQuestion
def edit
quiz_question_choices = QuizQuestionChoice.where(question_id: id)

data = {
id: id,
question_text: txt,
weight: weight,
choices: quiz_question_choices.each_with_index.map do |choice, index|
{
id: choice.id,
text: choice.txt,
is_correct: choice.iscorrect,
position: index + 1
}
end
}

data.to_json
end

def complete
quiz_question_choices = QuizQuestionChoice.where(question_id: id)

data = {
id: id,
question_text: txt,
choices: quiz_question_choices.map do |choice|
{ text: choice.txt }
end
}

data.to_json
end

def view_completed_question(user_answer)
quiz_question_choices = QuizQuestionChoice.where(question_id: id)

data = {
question_choices: quiz_question_choices.map do |choice|
{
text: choice.txt,
is_correct: choice.iscorrect
}
end,
user_answers: user_answer.map do |answer|
{
is_correct: answer.answer == 1,
comments: answer.comments
}
end
}

data.to_json
end

def isvalid(choice_info)
error_message = nil
error_message = 'Please make sure all questions have text' if txt.blank?

correct_count = choice_info.count { |_idx, value| value[:iscorrect] == '1' }

if correct_count.zero?
error_message = 'Please select a correct answer for all questions'
elsif correct_count == 1
error_message = 'A multiple-choice checkbox question should have more than one correct answer.'
end

{ valid: error_message.nil?, error: error_message }.to_json
end
end
Loading