diff --git a/app/controllers/admin/annotations_controller.rb b/app/controllers/admin/annotations_controller.rb new file mode 100644 index 0000000..dc0830e --- /dev/null +++ b/app/controllers/admin/annotations_controller.rb @@ -0,0 +1,21 @@ +module Admin + class AnnotationsController < Admin::ApplicationController + # To customize the behavior of this controller, + # you can overwrite any of the RESTful actions. For example: + # + # def index + # super + # @resources = SuggestedAnswer. + # page(params[:page]). + # per(10) + # end + + # Define a custom finder by overriding the `find_resource` method: + # def find_resource(param) + # SuggestedAnswer.find_by!(slug: param) + # end + + # See https://administrate-prototype.herokuapp.com/customizing_controller_actions + # for more information + end +end diff --git a/app/controllers/admin/suggested_answers_controller.rb b/app/controllers/admin/suggested_answers_controller.rb deleted file mode 100644 index 35d5243..0000000 --- a/app/controllers/admin/suggested_answers_controller.rb +++ /dev/null @@ -1,21 +0,0 @@ -module Admin - class SuggestedAnswersController < Admin::ApplicationController - # To customize the behavior of this controller, - # you can overwrite any of the RESTful actions. For example: - # - # def index - # super - # @resources = SuggestedAnswer. - # page(params[:page]). - # per(10) - # end - - # Define a custom finder by overriding the `find_resource` method: - # def find_resource(param) - # SuggestedAnswer.find_by!(slug: param) - # end - - # See https://administrate-prototype.herokuapp.com/customizing_controller_actions - # for more information - end -end diff --git a/app/controllers/annotations_controller.rb b/app/controllers/annotations_controller.rb new file mode 100644 index 0000000..a262cb3 --- /dev/null +++ b/app/controllers/annotations_controller.rb @@ -0,0 +1,53 @@ +class AnnotationsController < ApplicationController + respond_to :html + after_action :verify_authorized + + #create annotations + def admin_create + @example_answer = Annotation.new(params[:annotation]) + authorize @example_answer + if @example_answer.save + redirect_to admin_show_phase_path(id: @example_answer.question.section.phase_id, section_id: @example_answer.question.section_id, question_id: @example_answer.question.id, edit: 'true'), notice: _('Information was successfully created.') + else + @section = @example_answer.question.section + @phase = @section.phase + @open = true + @sections = @phase.sections + @section_id = @section.id + @question_id = @example_answer.question + flash[:notice] = failed_create_error(@example_answer, _('example answer')) + render "phases/admin_show" + end + end + + + #update a example answer of a template + def admin_update + @example_answer = Annotation.includes(question: { section: {phase: :template}}).find(params[:id]) + authorize @example_answer #.question.section.phase.template + @question = @example_answer.question + @section = @question.section + @phase = @section.phase + if @example_answer.update_attributes(params[:annotation]) + redirect_to admin_show_phase_path(id: @phase.id, section_id: @section.id, question_id: @question.id, edit: 'true'), notice: _('Information was successfully updated.') + else + flash[:notice] = failed_update_error(@example_answer, _('example answer')) + render action: "phases/admin_show" + end + end + + #delete an annotation + def admin_destroy + @example_answer = Annotation.includes(question: { section: {phase: :template}}).find(params[:id]) + authorize @example_answer + @question = @example_answer.question + @section = @question.section + @phase = @section.phase + if @example_answer.destroy + redirect_to admin_show_phase_path(id: @phase.id, section_id: @section.id, edit: 'true'), notice: _('Information was successfully deleted.') + else + redirect_to admin_show_phase_path(id: @phase.id, section_id: @section.id, edit: 'true'), notice: flash[:notice] = failed_destroy_error(@example_answer, _('example answer')) + end + end + +end \ No newline at end of file diff --git a/app/controllers/questions_controller.rb b/app/controllers/questions_controller.rb index 6ed74f3..14a6d21 100644 --- a/app/controllers/questions_controller.rb +++ b/app/controllers/questions_controller.rb @@ -6,12 +6,24 @@ def admin_create @question = Question.new(params[:question]) authorize @question - @question.guidance = params["new-question-guidance"] + example = @question.annotations.first + if example.present? + example.org_id = current_user.org_id + example.example_answer! + end + if params["new-question-guidance"].present? + guidance = @question.annotations.build + guidance.text = params["new-question-guidance"] + guidance.org_id = current_user.org_id + guidance.guidance! + guidance.save + end @question.default_value = params["new-question-default-value"] + @question.modifiable = true if @question.save @question.section.phase.template.dirty = true @question.section.phase.template.save! - + redirect_to admin_show_phase_path(id: @question.section.phase_id, section_id: @question.section_id, question_id: @question.id, edit: 'true'), notice: _('Information was successfully created.') else @edit = (@question.section.phase.template.org == current_user.org) @@ -21,7 +33,7 @@ @sections = @phase.sections @section_id = @question.section.id @question_id = @question.id - + flash[:notice] = failed_create_error(@question, _('question')) render template: 'phases/admin_show' end @@ -31,14 +43,23 @@ def admin_update @question = Question.find(params[:id]) authorize @question - @question.guidance = params["question-guidance-#{params[:id]}"] + guidance = @question.get_guidance_annotation(current_user.org_id) + if params["question-guidance-#{params[:id]}"].present? + if guidance.blank? + guidance = @question.annotations.build + guidance.type = :guidance + end + guidance.text = params["question-guidance-#{params[:id]}"] + guidance.save + end @question.default_value = params["question-default-value-#{params[:id]}"] @section = @question.section @phase = @section.phase + template = @phase.template if @question.update_attributes(params[:question]) - @question.section.phase.template.dirty = true - @question.section.phase.template.save! - + @phase.template.dirty = true + @phase.template.save! + redirect_to admin_show_phase_path(id: @phase.id, section_id: @section.id, question_id: @question.id, edit: 'true'), notice: _('Information was successfully updated.') else @edit = (@phase.template.org == current_user.org) @@ -46,7 +67,7 @@ @sections = @phase.sections @section_id = @section.id @question_id = @question.id - + flash[:notice] = failed_update_error(@question, _('question')) render template: 'phases/admin_show' end diff --git a/app/controllers/suggested_answers_controller.rb b/app/controllers/suggested_answers_controller.rb deleted file mode 100644 index e15d0c0..0000000 --- a/app/controllers/suggested_answers_controller.rb +++ /dev/null @@ -1,65 +0,0 @@ -class SuggestedAnswersController < ApplicationController - respond_to :html - after_action :verify_authorized - - #create suggested answers - def admin_create - @suggested_answer = SuggestedAnswer.new(params[:suggested_answer]) - authorize @suggested_answer - if @suggested_answer.save - # Set the template's dirty flag to true - @suggested_answer.question.section.phase.template.dirty = true - @suggested_answer.question.section.phase.template.save - - redirect_to admin_show_phase_path(id: @suggested_answer.question.section.phase_id, section_id: @suggested_answer.question.section_id, question_id: @suggested_answer.question.id, edit: 'true'), notice: _('Information was successfully created.') - else - @phase = @suggested_answer.question.section.phase - @section = @suggested_answer.question.section - @open = true - @sections = @phase.sections - @section_id = @section.id - @question_id = @suggested_answer.question - flash[:notice] = failed_create_error(@suggested_answer, _('suggested answer')) - render "phases/admin_show" - end - end - - - #update a suggested answer of a template - def admin_update - @suggested_answer = SuggestedAnswer.includes(question: { section: {phase: :template}}).find(params[:id]) - authorize @suggested_answer #.question.section.phase.template - @question = @suggested_answer.question - @section = @question.section - @phase = @section.phase - if @suggested_answer.update_attributes(params[:suggested_answer]) - # Set the template's dirty flag to true - @phase.template.dirty = true - @phase.template.save - - redirect_to admin_show_phase_path(id: @phase.id, section_id: @section.id, question_id: @question.id, edit: 'true'), notice: _('Information was successfully updated.') - else - flash[:notice] = failed_update_error(@suggested_answer, _('suggested answer')) - render action: "phases/admin_show" - end - end - - #delete a suggested answer - def admin_destroy - @suggested_answer = SuggestedAnswer.includes(question: { section: {phase: :template}}).find(params[:id]) - authorize @suggested_answer - @question = @suggested_answer.question - @section = @question.section - @phase = @section.phase - if @suggested_answer.destroy - # Set the template's dirty flag to true - @phase.template.dirty = true - @phase.template.save - - redirect_to admin_show_phase_path(id: @phase.id, section_id: @section.id, edit: 'true'), notice: _('Information was successfully deleted.') - else - redirect_to admin_show_phase_path(id: @phase.id, section_id: @section.id, edit: 'true'), notice: flash[:notice] = failed_destroy_error(@suggested_answer, _('suggested answer')) - end - end - -end \ No newline at end of file diff --git a/app/controllers/templates_controller.rb b/app/controllers/templates_controller.rb index 1f5efa4..261c1dd 100644 --- a/app/controllers/templates_controller.rb +++ b/app/controllers/templates_controller.rb @@ -1,5 +1,5 @@ # [+Project:+] DMPRoadmap -# [+Description:+] This controller is responsible for all the actions in the admin interface under templates (e.g. phases, versions, sections, questions, suggested answer) (index; show; create; edit; delete) +# [+Description:+] This controller is responsible for all the actions in the admin interface under templates (e.g. phases, versions, sections, questions, annotations) (index; show; create; edit; delete) # [+Copyright:+] Digital Curation Centre and University of California Curation Center class TemplatesController < ApplicationController @@ -10,30 +10,30 @@ # ----------------------------------------------------- def admin_index authorize Template - + funder_templates, org_templates, customizations = [], [], [] - + # Get all of the unique template family ids (dmptemplate_id) for each funder and the current org funder_ids = Org.funders.includes(:templates).collect{|f| f.templates.collect{|ft| ft.dmptemplate_id } }.flatten.uniq org_ids = current_user.org.templates.collect{|t| t.dmptemplate_id }.flatten.uniq - + org_ids.each do |id| current = Template.current(id) live = Template.live(id) - + # If this isn't a customization of a funder template if current.customization_of.nil? org_templates << {current: current, live: live} - + # This is a customization of a funder template else funder_live = Template.live(current.customization_of) customizations << current.customization_of # Mark the customization as stale if the funder has a newer version - funder_templates << {current: current, live: live, stale: funder_live.updated_at > current.created_at} + funder_templates << {current: current, live: live, stale: funder_live.updated_at > current.created_at} end end - + # Get the funder templates funder_ids.each do |id| # If the org has a customization we don't want to load the funder version @@ -41,11 +41,11 @@ funder_templates << {current: Template.current(id), live: Template.live(id)} end end - - @funder_templates = funder_templates.sort{|x,y| + + @funder_templates = funder_templates.sort{|x,y| x[:current].title <=> y[:current].title } - @org_templates = org_templates.sort{|x,y| + @org_templates = org_templates.sort{|x,y| x[:current].title <=> y[:current].title } end @@ -55,7 +55,7 @@ def admin_customize @template = Template.find(params[:id]) authorize @template - + customisation = Template.deep_copy(@template) customisation.org = current_user.org customisation.version = 0 @@ -65,7 +65,7 @@ break random unless Template.exists?(dmptemplate_id: random) end customisation.save - + customisation.phases.includes(:sections, :questions).each do |phase| phase.modifiable = false phase.save! @@ -78,10 +78,10 @@ end end end - + redirect_to admin_template_template_path(customisation) end - + # PUT /org/admin/templates/:id/admin_publish # ----------------------------------------------------- def admin_publish @@ -89,7 +89,7 @@ authorize @template current = Template.current(@template.dmptemplate_id) - + # Only allow the current version to be updated if current != @template redirect_to admin_template_template_path(@template), notice: _('You can not publish a historical version of this template.') @@ -106,7 +106,7 @@ @template.published = true @template.save - # Create a new version + # Create a new version new_version = Template.deep_copy(@template) new_version.version = (@template.version + 1) new_version.published = false @@ -134,23 +134,22 @@ @template.save flash[:notice] = _('Your template is no longer published. Users will not be able to create new DMPs for this template until you re-publish it') end - + redirect_to admin_index_template_path(current_user.org) end # GET /org/admin/templates/:id/admin_template # ----------------------------------------------------- def admin_template - @template = Template.includes(:org, phases: [sections: [questions: [:question_options, :question_format, - :suggested_answers]]]).find(params[:id]) + @template = Template.includes(:org, phases: [sections: [questions: [:question_options, :question_format, :annotations]]]).find(params[:id]) authorize @template - + @current = Template.current(@template.dmptemplate_id) - + unless @template == @current flash[:notice] = _('You are viewing a historical version of this template. You will not be able to make changes.') end - + # once the correct template has been generated, we convert it to hash @hash = @template.to_hash end @@ -161,9 +160,9 @@ def admin_update @template = Template.find(params[:id]) authorize @template - + current = Template.current(@template.dmptemplate_id) - + # Only allow the current version to be updated if current != @template redirect_to admin_template_template_path(@template), notice: _('You can not edit a historical version of this template.') @@ -173,18 +172,18 @@ @template.title != params[:template][:title] @template.dirty = true end - + @template.description = params["template-desc"] if @template.update_attributes(params[:template]) flash[:notice] = _('Information was successfully updated.') - + else flash[:notice] = failed_update_error(@template, _('template')) end - + @hash = @template.to_hash render 'admin_template' - end + end end @@ -219,9 +218,9 @@ def admin_destroy @template = Template.find(params[:id]) authorize @template - + current = Template.current(@template.dmptemplate_id) - + # Only allow the current version to be destroyed if current == @template if @template.destroy diff --git a/app/dashboards/annotation_dashboard.rb b/app/dashboards/annotation_dashboard.rb new file mode 100644 index 0000000..add7afa --- /dev/null +++ b/app/dashboards/annotation_dashboard.rb @@ -0,0 +1,60 @@ +require "administrate/base_dashboard" + +class AnnotationDashboard < Administrate::BaseDashboard + # ATTRIBUTE_TYPES + # a hash that describes the type of each of the model's fields. + # + # Each different type represents an Administrate::Field object, + # which determines how the attribute is displayed + # on pages throughout the dashboard. + ATTRIBUTE_TYPES = { + org: Field::BelongsTo, + question: Field::BelongsTo, + id: Field::Number, + text: Field::Text, + type: Field::integer, + created_at: Field::DateTime, + updated_at: Field::DateTime, + }.freeze + + # COLLECTION_ATTRIBUTES + # an array of attributes that will be displayed on the model's index page. + # + # By default, it's limited to four items to reduce clutter on index pages. + # Feel free to add, remove, or rearrange items. + COLLECTION_ATTRIBUTES = [ + :org, + :question, + :id, + :text, + ].freeze + + # SHOW_PAGE_ATTRIBUTES + # an array of attributes that will be displayed on the model's show page. + SHOW_PAGE_ATTRIBUTES = [ + :org, + :question, + :id, + :text, + :type, + :created_at, + :updated_at, + ].freeze + + # FORM_ATTRIBUTES + # an array of attributes that will be displayed + # on the model's form (`new` and `edit`) pages. + FORM_ATTRIBUTES = [ + :org, + :question, + :text, + :type, + ].freeze + + # Overwrite this method to customize how suggested answers are displayed + # across all pages of the admin dashboard. + # + # def display_resource(suggested_answer) + # "SuggestedAnswer ##{suggested_answer.id}" + # end +end diff --git a/app/dashboards/org_dashboard.rb b/app/dashboards/org_dashboard.rb index 013748f..c00db7b 100644 --- a/app/dashboards/org_dashboard.rb +++ b/app/dashboards/org_dashboard.rb @@ -12,7 +12,7 @@ guidance_groups: Field::HasMany, templates: Field::HasMany, users: Field::HasMany, - suggested_answers: Field::HasMany, + annotations: Field::HasMany, token_permission_types: Field::HasMany, id: Field::Number, name: Field::String, @@ -59,7 +59,7 @@ :contact_email, :org_type, :users, - :suggested_answers, + :annotations, :token_permission_types, :id, :target_url, @@ -84,7 +84,7 @@ :guidance_groups, # :templates, # :users, -# :suggested_answers, +# :annotations, :token_permission_types, :name, :abbreviation, diff --git a/app/dashboards/question_dashboard.rb b/app/dashboards/question_dashboard.rb index 1d1f8aa..af3d8bb 100644 --- a/app/dashboards/question_dashboard.rb +++ b/app/dashboards/question_dashboard.rb @@ -10,7 +10,7 @@ ATTRIBUTE_TYPES = { answers: Field::HasMany, question_options: Field::HasMany, - suggested_answers: Field::HasMany, + annotations: Field::HasMany, themes: Field::HasMany, section: Field::BelongsTo, question_format: Field::BelongsTo, @@ -33,7 +33,7 @@ COLLECTION_ATTRIBUTES = [ :answers, :question_options, - :suggested_answers, + :annotations, :themes, ].freeze @@ -42,7 +42,7 @@ SHOW_PAGE_ATTRIBUTES = [ :answers, :question_options, - :suggested_answers, + :annotations, :themes, :section, :question_format, @@ -63,7 +63,7 @@ FORM_ATTRIBUTES = [ :answers, :question_options, - :suggested_answers, + :annotations, :themes, :section, :question_format, diff --git a/app/dashboards/suggested_answer_dashboard.rb b/app/dashboards/suggested_answer_dashboard.rb deleted file mode 100644 index 980ef11..0000000 --- a/app/dashboards/suggested_answer_dashboard.rb +++ /dev/null @@ -1,60 +0,0 @@ -require "administrate/base_dashboard" - -class SuggestedAnswerDashboard < Administrate::BaseDashboard - # ATTRIBUTE_TYPES - # a hash that describes the type of each of the model's fields. - # - # Each different type represents an Administrate::Field object, - # which determines how the attribute is displayed - # on pages throughout the dashboard. - ATTRIBUTE_TYPES = { - org: Field::BelongsTo, - question: Field::BelongsTo, - id: Field::Number, - text: Field::Text, - is_example: Field::Boolean, - created_at: Field::DateTime, - updated_at: Field::DateTime, - }.freeze - - # COLLECTION_ATTRIBUTES - # an array of attributes that will be displayed on the model's index page. - # - # By default, it's limited to four items to reduce clutter on index pages. - # Feel free to add, remove, or rearrange items. - COLLECTION_ATTRIBUTES = [ - :org, - :question, - :id, - :text, - ].freeze - - # SHOW_PAGE_ATTRIBUTES - # an array of attributes that will be displayed on the model's show page. - SHOW_PAGE_ATTRIBUTES = [ - :org, - :question, - :id, - :text, - :is_example, - :created_at, - :updated_at, - ].freeze - - # FORM_ATTRIBUTES - # an array of attributes that will be displayed - # on the model's form (`new` and `edit`) pages. - FORM_ATTRIBUTES = [ - :org, - :question, - :text, - :is_example, - ].freeze - - # Overwrite this method to customize how suggested answers are displayed - # across all pages of the admin dashboard. - # - # def display_resource(suggested_answer) - # "SuggestedAnswer ##{suggested_answer.id}" - # end -end diff --git a/app/models/annotation.rb b/app/models/annotation.rb new file mode 100644 index 0000000..66b58e6 --- /dev/null +++ b/app/models/annotation.rb @@ -0,0 +1,40 @@ +class Annotation < ActiveRecord::Base + enum type: [ :guidance, :example_answer] + ## + # Associations + belongs_to :org + belongs_to :question + + ## + # I liked type as the name for the enum so overriding inheritance column + self.inheritance_column = nil + + ## + # Possibly needed for active_admin + # -relies on protected_attributes gem as syntax depricated in rails 4.2 + attr_accessible :org_id, :question_id, :text, :type, + :org, :question, :as => [:default, :admin] + + + validates :question, :org, presence: {message: _("can't be blank")} + + ## + # returns the text from the annotation + # + # @return [String] the text from the annotation + def to_s + "#{text}" + end + + + ## + # deep copy the given annotation and all it's associations + # + # @params [Annotation] annotation to be deep copied + # @return [Annotation] the saved, copied annotation + def self.deep_copy(annotation) + annotation_copy = annotation.dup + annotation_copy.save! + return annotation_copy + end +end \ No newline at end of file diff --git a/app/models/org.rb b/app/models/org.rb index e11d5e1..e754693 100644 --- a/app/models/org.rb +++ b/app/models/org.rb @@ -10,7 +10,7 @@ has_many :guidance_groups has_many :templates has_many :users - has_many :suggested_answers + has_many :annotations has_and_belongs_to_many :token_permission_types, join_table: "org_token_permissions", unique: true diff --git a/app/models/plan.rb b/app/models/plan.rb index 8c8d3c7..549b4fe 100644 --- a/app/models/plan.rb +++ b/app/models/plan.rb @@ -970,7 +970,7 @@ def self.eager_load2(id) Plan.includes( [{template: [ - {phases: {sections: {questions: [{answers: :notes}, :suggested_answers, :question_format, :themes]}}}, + {phases: {sections: {questions: [{answers: :notes}, :annotations, :question_format, :themes]}}}, {customizations: :org}, :org ]}, diff --git a/app/models/question.rb b/app/models/question.rb index 336cae9..10efc8b 100644 --- a/app/models/question.rb +++ b/app/models/question.rb @@ -3,7 +3,7 @@ # Associations has_many :answers, :dependent => :destroy has_many :question_options, :dependent => :destroy - has_many :suggested_answers, :dependent => :destroy + has_many :annotations, :dependent => :destroy has_and_belongs_to_many :themes, join_table: "questions_themes" belongs_to :section belongs_to :question_format @@ -13,17 +13,17 @@ # TODO: evaluate if we need this accepts_nested_attributes_for :answers, :reject_if => lambda {|a| a[:text].blank? }, :allow_destroy => true accepts_nested_attributes_for :question_options, :reject_if => lambda {|a| a[:text].blank? }, :allow_destroy => true - accepts_nested_attributes_for :suggested_answers, :allow_destroy => true + accepts_nested_attributes_for :annotations, :allow_destroy => true accepts_nested_attributes_for :themes ## # Possibly needed for active_admin # -relies on protected_attributes gem as syntax depricated in rails 4.2 attr_accessible :default_value, :dependency_id, :dependency_text, :guidance,:number, - :suggested_answer, :text, :section_id, :question_format_id, - :question_options_attributes, :suggested_answers_attributes, + :annotation, :text, :section_id, :question_format_id, + :question_options_attributes, :annotations_attributes, :option_comment_display, :theme_ids, :section, :question_format, - :question_options, :suggested_answers, :answers, :themes, + :question_options, :annotations, :answers, :themes, :modifiable, :option_comment_display, :as => [:default, :admin] validates :text, :section, :number, presence: {message: _("can't be blank")} @@ -65,10 +65,10 @@ question_option_copy.question_id = question_copy.id question_option_copy.save! end - question.suggested_answers.each do |suggested_answer| - suggested_answer_copy = SuggestedAnswer.deep_copy(suggested_answer) - suggested_answer_copy.question_id = question_copy.id - suggested_answer_copy.save! + question.annotations.each do |annotation| + annotation_copy = Annotation.deep_copy(annotation) + annotation_copy.question_id = question_copy.id + annotation_copy.save! end question.themes.each do |theme| question_copy.themes << theme @@ -101,13 +101,24 @@ end ## - # get suggested answer belonging to the currents user for this question + # get example answer belonging to the currents user for this question # # @param org_id [Integer] the id for the organisation - # @return [String] the suggested_answer for this question for the specified organisation - def get_suggested_answer(org_id) - suggested_answer = suggested_answers.find_by(org_id: org_id) - return suggested_answer + # @return [String] the example answer for this question for the specified org + def get_example_answer(org_id) + example_answer = self.annotations.where(org_id: org_id).where(type: Annotation.types[:example_answer]).order(:created_at) + return example_answer.first end + ## + # get guidance belonging to the current user's org for this question(need org + # to distinguish customizations) + # + # @param org_id [Integer] the id for the organisation + # @return [String] the annotation guidance for this question for the specified org + def get_guidance_annotation(org_id) + guidance = self.annotations.where(org_id: org_id).where(type: Annotation.types[:guidance]) + return guidance.first + end + end diff --git a/app/models/suggested_answer.rb b/app/models/suggested_answer.rb deleted file mode 100644 index 881f302..0000000 --- a/app/models/suggested_answer.rb +++ /dev/null @@ -1,42 +0,0 @@ -class SuggestedAnswer < ActiveRecord::Base - - ## - # Associations - belongs_to :org - belongs_to :question - - ## - # Possibly needed for active_admin - # -relies on protected_attributes gem as syntax depricated in rails 4.2 - attr_accessible :org_id, :question_id, :text, :is_example, - :org, :question, :as => [:default, :admin] - - - validates :question, :org, presence: {message: _("can't be blank")} - - # EVALUATE CLASS AND INSTANCE METHODS BELOW - # - # What do they do? do they do it efficiently, and do we need them? - - - - ## - # returns the text from the suggested_answer - # - # @return [String] the text from the suggested_answer - def to_s - "#{text}" - end - - - ## - # deep copy the given question_option and all it's associations - # - # @params [QuestionOption] question_option to be deep copied - # @return [QuestionOption] the saved, copied question_option - def self.deep_copy(suggested_answer) - suggested_answer_copy = suggested_answer.dup - suggested_answer_copy.save! - return suggested_answer_copy - end -end \ No newline at end of file diff --git a/app/models/template.rb b/app/models/template.rb index 94a845b..f7d5639 100644 --- a/app/models/template.rb +++ b/app/models/template.rb @@ -67,11 +67,11 @@ ## # convert the given template to a hash and return with all it's associations - # to use, please pre-fetch org, phases, section, questions, suggested_answers, + # to use, please pre-fetch org, phases, section, questions, annotations, # question_options, question_formats, # TODO: Themes & guidance? # - # @return [hash] hash of template, phases, sections, questions, question_options, suggested_answers + # @return [hash] hash of template, phases, sections, questions, question_options, annotations def to_hash hash = {} hash[:template] = {} @@ -90,10 +90,10 @@ section.questions.each do |question| phases[phase.number][:sections][section.number][:questions][question.number] = {} phases[phase.number][:sections][section.number][:questions][question.number][:data] = question - phases[phase.number][:sections][section.number][:questions][question.number][:suggested_answers] = {} - question.suggested_answers.each do |suggested_answer| - phases[phase.number][:sections][section.number][:questions][question.number][:suggested_answers][suggested_answer.id] = {} - phases[phase.number][:sections][section.number][:questions][question.number][:suggested_answers][suggested_answer.id][:data] = suggested_answer + phases[phase.number][:sections][section.number][:questions][question.number][:annotations] = {} + question.annotations.each do |annotation| + phases[phase.number][:sections][section.number][:questions][question.number][:annotations][annotation.id] = {} + phases[phase.number][:sections][section.number][:questions][question.number][:annotations][annotation.id][:data] = annotation end phases[phase.number][:sections][section.number][:questions][question.number][:question_options] = {} question.question_options.each do |question_option| diff --git a/app/policies/annotation_policy.rb b/app/policies/annotation_policy.rb new file mode 100644 index 0000000..cf63f42 --- /dev/null +++ b/app/policies/annotation_policy.rb @@ -0,0 +1,28 @@ +class AnnotationPolicy < ApplicationPolicy + attr_reader :user, :annotation + + def initialize(user, annotation) + raise Pundit::NotAuthorizedError, "must be logged in" unless user + @user = user + @annotation = annotation + end + + ## + # Users can modify annotations if: + # - They can modify templates + # - The template which they are modifying belongs to their orggi + ## + + def admin_create? + user.can_modify_templates? && (annotation.question.section.phase.template.org_id == user.org_id) + end + + def admin_update? + user.can_modify_templates? && (annotation.question.section.phase.template.org_id == user.org_id) + end + + def admin_destroy? + user.can_modify_templates? && (annotation.question.section.phase.template.org_id == user.org_id) + end + +end \ No newline at end of file diff --git a/app/policies/suggested_answer_policy.rb b/app/policies/suggested_answer_policy.rb deleted file mode 100644 index e6cd49c..0000000 --- a/app/policies/suggested_answer_policy.rb +++ /dev/null @@ -1,28 +0,0 @@ -class SuggestedAnswerPolicy < ApplicationPolicy - attr_reader :user, :suggested_answer - - def initialize(user, suggested_answer) - raise Pundit::NotAuthorizedError, "must be logged in" unless user - @user = user - @suggested_answer = suggested_answer - end - - ## - # Users can modify suggested answers if: - # - They can modify templates - # - The template which they are modifying belongs to their org - ## - - def admin_create? - user.can_modify_templates? && (suggested_answer.question.section.phase.template.org_id == user.org_id) - end - - def admin_update? - user.can_modify_templates? && (suggested_answer.question.section.phase.template.org_id == user.org_id) - end - - def admin_destroy? - user.can_modify_templates? && (suggested_answer.question.section.phase.template.org_id == user.org_id) - end - -end \ No newline at end of file diff --git a/app/views/annotations/_add_annotation.html.erb b/app/views/annotations/_add_annotation.html.erb new file mode 100644 index 0000000..8cf9113 --- /dev/null +++ b/app/views/annotations/_add_annotation.html.erb @@ -0,0 +1,25 @@ + +<%= form_for :annotation, url: admin_create_annotation_path do |f| %> + <%= f.hidden_field :org_id, value: current_user.org_id %> + <%= f.hidden_field :question_id, value: question.id %> + <%= f.hidden_field :type, value: Annotation.types[:example_answer] %> + + + + + + +
<%= _('Example Answer')%> +
    +
  • <%= f.text_area :text, rows: 5 %> +
  • +
+
+
+ + +
+ <%= f.submit _('Save'), class: "btn btn-primary" %> + <%= link_to _('Cancel'), "#", id: "cancel_suugested_answer", class: "btn cancel" %> +
+<%end%> diff --git a/app/views/annotations/_edit_annotation.html.erb b/app/views/annotations/_edit_annotation.html.erb new file mode 100644 index 0000000..6fa1e35 --- /dev/null +++ b/app/views/annotations/_edit_annotation.html.erb @@ -0,0 +1,25 @@ + +<%= form_for( annotation, url: admin_update_annotation_path(annotation.id), html: { method: :put}) do |f| %> + <%= f.hidden_field :org_id, value: current_user.org_id %> + + + + + + +
<%= _('Example of Answer')%> +
    +
  • <%= f.text_area :text, rows: 5 %>
  • +
+
+
+ + +
+ <%= f.submit _('Save'), class: 'btn btn-primary' %> + <%= link_to _('Delete'), admin_destroy_annotation_path(id: annotation.id), + confirm: _("You are about to delete an example answer for '%{question_text}'. Are you sure?") % { :question_text => question.text }, method: :delete, class: "btn btn-primary"%> + <%= hidden_field_tag :question_id, question.id, class: "question_id" %> + <%= link_to _('Cancel'), '#', class: 'btn cancel cancel_edit_suggested_answer' %> +
+<% end %> diff --git a/app/views/annotations/_show_annotation.html.erb b/app/views/annotations/_show_annotation.html.erb new file mode 100644 index 0000000..9cc93de --- /dev/null +++ b/app/views/annotations/_show_annotation.html.erb @@ -0,0 +1,15 @@ + + + + + + +
+ <%= _('Example of answer')%> + <%= raw annotation.text %>
+
+ +
+ <%= hidden_field_tag :question_id, question.id, class: "question_id" %> + <%= link_to _('Edit Example of Answer'), '# ', class: "btn btn-primary edit_form_for_suggested_answer"%> +
diff --git a/app/views/guidances/_edit_guidance.html.erb b/app/views/guidances/_edit_guidance.html.erb index 36fe926..7138ceb 100644 --- a/app/views/guidances/_edit_guidance.html.erb +++ b/app/views/guidances/_edit_guidance.html.erb @@ -1,4 +1,4 @@ - + <%= form_for(suggested_answer, url: admin_update_suggested_answer_path(suggested_answer), html: { method: :put}) do |f| %> <%= f.hidden_field :org_id, value: current_user.org_id %> diff --git a/app/views/phases/_answer_form.html.erb b/app/views/phases/_answer_form.html.erb index bdd8c1d..7a1ab93 100644 --- a/app/views/phases/_answer_form.html.erb +++ b/app/views/phases/_answer_form.html.erb @@ -31,22 +31,18 @@ <%= raw question.text %> - - <% if question.suggested_answers.any? %> - <% suggested_answer = question.suggested_answers.first %> - <% if suggested_answer.text.present? %> + + <% if question.annotations.where('type <> ?',Annotation.types[:example_answer]).any? %> + <% annotation = question.annotations.where('type <> ?',Annotation.types[:example_answer]).order(:created_at).first %> + <% if annotation.text.present? %>
- <% if suggested_answer.is_example? then %> - <%= _('Example of answer')%> - <%else%> - <%= _('Suggested answer')%> - <%end%> + <%="#{annotation.org.abbreviation} "%> <%=_('Example of answer')%>

- <%= raw suggested_answer.text %> + <%= raw annotation.text %>

@@ -119,7 +115,8 @@ <% comments = answer.notes.all %> <%= hidden_field_tag :question_id, question_id, class: "question_id" %> @@ -155,25 +152,28 @@
- - <% if question.guidance.present? %> -
+ + <% if annotations.present? %> + <% annotations.each do |annotation| %> - - +
- -
-
<%= raw question.guidance %>
-
+ + -
+ +
+
<%= raw annotation.text %>
+
+ +
+ <% end %> <% end %> @@ -182,13 +182,13 @@ <% group.each do |gobj| %>
-
+
<%= raw gobj[:text] %>
<% guidance_accordion_id += 1 %> diff --git a/app/views/phases/_answer_form_ro.html.erb b/app/views/phases/_answer_form_ro.html.erb index 4f68019..fcf175d 100644 --- a/app/views/phases/_answer_form_ro.html.erb +++ b/app/views/phases/_answer_form_ro.html.erb @@ -23,19 +23,15 @@ <%= raw question.text %> - <% suggested_answer = question.suggested_answers.where(org_id: @plan.template.org_id).first %> - <% if suggested_answer.present? %> + <<% if question.annotations.where('type <> ?',Annotation.types[:example_answer]).any? %> + <% annotation = question.annotations.where('type <> ?',Annotation.types[:example_answer]).order(:created_at).first %>
- <% if suggested_answer.is_example? then %> - <%= _('Example of answer')%> - <%else%> - <%= _('Suggested answer')%> - <%end%> + <%= _('Example of answer')%>

- <%= raw suggested_answer.text %> + <%= raw annotation.text %>

diff --git a/app/views/plans/_answer_form.html.erb b/app/views/plans/_answer_form.html.erb deleted file mode 100644 index 45f908b..0000000 --- a/app/views/plans/_answer_form.html.erb +++ /dev/null @@ -1,269 +0,0 @@ - -<% answer = @plan.answer(question.id) %> - -
- - <% q_format = question.question_format%> - - <% if readonly != "always" then %> -
> - <%= semantic_form_for answer, :url => {:controller => :answers, :action => :create }, :html=>{:method=>:post}, :remote => true do |f| %> - <%= f.inputs do %> - <%= f.input :plan_id, :as => :hidden %> - <%= f.input :user_id, :as => :hidden, :input_html => { :value => current_user.id } %> - <%= f.input :question_id, :as => :hidden, :input_html => { :class => "question_id" } %> - - - - <%= raw question.text %> - - - <% suggested_answer = question.suggested_answers.find_by_organisation_id(@plan.project.organisation_id) %> - <% if !suggested_answer.nil? && suggested_answer.text != "" then %> -
- - <% if suggested_answer.is_example? then %> - <%= _('Example of answer')%> - <%else%> - <%= _('Suggested answer')%> - <%end%> - -
-

- <%= raw suggested_answer.text %> -

-
-
- <% end %> - - - <% if q_format.title == "Check box" || - q_format.title == "Multi select box" || - q_format.title == "Radio buttons" || - q_format.title == "Dropdown" then%> - <% options = question.options.order("number") %> - - <% if q_format.title == "Check box" then %> - <% if readonly then %> - <%= f.input :options, :as => :check_boxes, :collection => options, :label => false, input_html => { :disabled => true, :id => "options-#{question.id}" } %> - <% else %> - <%= f.input :options, :as => :check_boxes, :collection => options, :label => false, :input_html => { :id => "options-#{question.id}" } %> - <% end %> - - <% elsif q_format.title == "Multi select box" then %> - <% if readonly then %> - <%= f.input :options, :as => :select, :collection => options, :label => false, :input_html => { :multiple => true, :disabled => true , :id => "options-#{question.id}" } %> - <% else %> - <%= f.input :options, :as => :select, :collection => options, :label => false, :input_html => { :multiple => true , :id => "options-#{question.id}" } %> - <% end %> - - <% elsif q_format.title == "Radio buttons" then%> -
    - <% options.each do |op| %> -
  1. - <% if answer.option_ids[0] == op.id then%> - <% if readonly then %> - <%= f.radio_button :option_ids, op.id, :checked => true, disabled: true, id: "answer_option_ids_#{op.id}"%> - <% else %> - <%= f.radio_button :option_ids, op.id, :checked => true, id: "answer_option_ids_#{op.id}"%> - <% end %> - <%else%> - <% if readonly then %> - <%= f.radio_button :option_ids, op.id, :checked => false, disabled: true, id: "answer_option_ids_#{op.id}"%> - <% else %> - <%= f.radio_button :option_ids, op.id, :checked => false, id: "answer_option_ids_#{op.id}"%> - <% end %> - <% end %> - <%= op.text %>
  2. - <% end %> -
- - <% elsif q_format.title == "Dropdown" then%> - <% if readonly then %> - <%= f.input :options, :as => :select, :collection => options, :label => false, :input_html => { :multiple => false, :disabled => true, :id => "options-#{question.id}" } %> - <% else %> - <%= f.input :options, :as => :select, :collection => options, :label => false, :input_html => { :multiple => false, :id => "options-#{question.id}" } %> - <% end %> - <% end %> - - - - - <% if question.option_comment_display == true then%> - <%= label_tag("answer-text-#{question.id}".to_sym, _('Comment')) %> - <%= text_area_tag("answer-text-#{question.id}".to_sym, answer.text, class: "tinymce") %> - <%end%> - - - <% elsif q_format.title == "Text field" then %> - <%= text_field_tag("answer-text-#{question.id}".to_sym, strip_tags(answer.text), class: "question_text_field") %> - - <% elsif q_format.title == "Text area" then%> - <%= text_area_tag("answer-text-#{question.id}".to_sym, answer.text, class: "tinymce") %> - <% end %> - - <% end %> - - - <%= f.actions do %> - <% if readonly then %> - <%= f.action :submit, :label => _('Save'), :button_html => { :class => "btn btn-primary"}, :input_html => { :disabled => true } %> - <% else %> - <%= f.action :submit, :label => _('Save'), :button_html => { :class => "btn btn-primary"} %> - - <% end %> - - <% end %> - <% end %> -
- <% end %> - -
> -

<%= question.text %>

-
- <% if q_format.title == "Check box" || - q_format.title == "Multi select box" || - q_format.title == "Radio buttons" || - q_format.title == "Dropdown" %> -
    - <% if answer.options.is_a? Option then %> -
  • <%= answer.options.text %>
  • - <% else %> - <% answer.options.each do |o| %> -
  • <%= o.text %>
  • - <% end %> - <% end %> -
- <% end %> -
- <%= raw answer.text %> -
-
-
- <% if answer.created_at.nil? then %> - <%= _('Not answered yet') %> - <% else %> - <%= _('Answered')%><%= answer.created_at %><%= _(' by')%><%= answer.user.name %> - <% end %> - -
- - - -
-
- <% @comments = Comment.where("question_id = ? AND plan_id = ?", question.id, answer.plan_id ) %> - <%= hidden_field_tag :question_id, question.id, :class => "question_id" %> - <% @question_guidances = @plan.guidance_for_question(question) %> -
    - <% if (!question.guidance.nil? && question.guidance != "") || @question_guidances.count > 0 then %> - - <% css_style_comment_div = "display: none;"%> - <% css_style_guidance_div = ""%> -
  • - <%= link_to _('Guidance'), "#", :class => "guidance_accordion_button" %> -
  • -
  • - <% if @comments.count > 0 then%> - <% comments_label_with_count = "#{_('Notes')} (#{@comments.count})"%> - <%= link_to comments_label_with_count , "#", :class => "comments_accordion_button" %> - <%else%> - <%= link_to _('Share note'), "#", :class => "comments_accordion_button" %> - <%end%> -
  • - <%else%> - - <% css_style_comment_div = ""%> - <% css_style_guidance_div = "display: none;"%> -
  • - <% if @comments.count > 0 then%> - <% comments_label_with_count = "#{_('Notes')} (#{@comments.count})"%> -

    <%= comments_label_with_count %>

    - <%else%> -

    <%= _('Share note') %>

    - <%end%> -
  • - <%end%> -
-
- - - -
-
- - <% if !question.guidance.nil? && question.guidance != "" then %> - - <% end %> - - <% @question_guidances.each_pair do |group,themes| %> - <% themes.each_pair do |theme,guidances| %> - <% guidances.each do |guidance| %> - - <% end %> - <% end %> - <% end %> -
-
- - -
- <%= render :partial => "comments", locals: {questionId: question.id, plan_id: answer.plan_id }%> -
- - - -
- -<% if last_question_id == question.id then %> -
-<% else %> -
-<% end %> diff --git a/app/views/questions/_add_question.html.erb b/app/views/questions/_add_question.html.erb index 3a95f58..9ca04bf 100644 --- a/app/views/questions/_add_question.html.erb +++ b/app/views/questions/_add_question.html.erb @@ -114,20 +114,20 @@ - <%= _('Suggested answer/ Example')%> + <%= _('Example Answer')%>
- <% suggested_answer = @new_question.suggested_answers.build %> - <%= f.fields_for :suggested_answers, suggested_answer do |s|%> + <% example_answer = @new_question.annotations.build %> + <% example_answer.type = :example_answer %> + <%= f.fields_for :annotations, example_answer do |s|%> <%= s.hidden_field :org_id, value: current_user.org_id %>
    -
  • <%= s.select :is_example, {_('Example of answer') => true, _('Suggested answer') => false} %>
  • <%= s.text_area :text, rows: 5 %>
<% end %>
- <%= link_to( image_tag("help_button.png"), "#", class: "suggested_answer_popover", rel: "popover", "data-html" => "true", "data-content" => _('You can add an example or suggested answer to help users respond. These will be presented above the answer box and can be copied/ pasted.'))%> + <%= link_to( image_tag("help_button.png"), "#", class: "suggested_answer_popover", rel: "popover", "data-html" => "true", "data-content" => _('You can add an example answer to help users respond. These will be presented above the answer box and can be copied/ pasted.'))%>
diff --git a/app/views/questions/_edit_question.html.erb b/app/views/questions/_edit_question.html.erb index 6c3d573..a0928df 100644 --- a/app/views/questions/_edit_question.html.erb +++ b/app/views/questions/_edit_question.html.erb @@ -106,16 +106,16 @@ - <%= _('Suggested answer/ Example')%> + <%= _('Example Answer')%>
- <% suggested_answer = question.suggested_answers.find_by_org_id(current_user.org.id) %> - <% if suggested_answer.nil? %> - <% suggested_answer = question.suggested_answers.build %> + <% example_answer = question.get_example_answer(current_user.org.id) %> + <% if example_answer.nil? %> + <% example_answer = question.annotations.build %> + <% example_answer.type = :example_answer %> <% end %> - <%= f.fields_for :suggested_answers, suggested_answer do |s|%> + <%= f.fields_for :annotations, example_answer do |s|%> <%= s.hidden_field :org_id, value: current_user.org.id %>
    -
  • <%= s.select :is_example, {_('Example of answer') => true, _('Suggested answer') => false} %>
  • <%= s.text_area :text, rows: 5 %>
@@ -132,7 +132,9 @@ <%= _('Guidance')%>
- <%= text_area_tag("question-guidance-#{question.id}", question.guidance , class: "tinymce") %> + <% guidance = question.get_guidance_annotation(current_user.org_id) %> + <% guidance_text = guidance.present? ? guidance.text : "" %> + <%= text_area_tag("question-guidance-#{question.id}", guidance_text , class: "tinymce") %>
<%= link_to( image_tag("help_button.png"), "#", class: "question_guidance_popover", rel: "popover", "data-html" => "true", "data-content" => _("Enter specific guidance to accompany this question. If you have guidance by themes too, this will be pulled in based on your selections below so it's best not to duplicate too much text."))%> diff --git a/app/views/questions/_preview_question.html.erb b/app/views/questions/_preview_question.html.erb index dc51641..e4a86a8 100644 --- a/app/views/questions/_preview_question.html.erb +++ b/app/views/questions/_preview_question.html.erb @@ -57,19 +57,15 @@ <% end %> - <% suggested_answer = question.suggested_answers.find_by(org_id: current_user.org_id) %> - <% if !suggested_answer.blank? %> + <% if question.annotations.where('type <> ?',Annotation.types[:example_answer]).any? %> + <% annotation = question.annotations.where('type <> ?',Annotation.types[:example_answer]).order(:created_at).first %>
- <% if suggested_answer.is_example? %> <%= _('Example of answer')%> - <% else %> - <%= _('Suggested answer')%> - <% end %>

- <%= raw suggested_answer.text %> + <%= raw annotation.text %>

@@ -80,19 +76,15 @@ <% else %> - <% suggested_answer = question.suggested_answers.find_by(org_id: current_user.org_id) %> - <% if !suggested_answer.blank? %> + <% annotations = question.annotations.find_by(org_id: current_user.org_id) %> + <% if !annotations.blank? %>
- <% if suggested_answer.is_example? %> <%= _('Example of answer')%> - <% else %> - <%= _('Suggested answer')%> - <% end %>

- <%= raw suggested_answer.text %> + <%= raw annotations.text %>

@@ -106,9 +98,9 @@ <% if q_format.title == _('Text field') %> - <%elsif q_format.title == _('Text area') %> + <% elsif q_format.title == _('Text area') %> - <%end%> + <% end %>
<%= link_to _('Save'), "#", class: "btn btn-primary", onclick: "event.preventDefault();" %> diff --git a/app/views/questions/_show_question.html.erb b/app/views/questions/_show_question.html.erb index 754d330..1f3423b 100644 --- a/app/views/questions/_show_question.html.erb +++ b/app/views/questions/_show_question.html.erb @@ -63,25 +63,22 @@ <% if !question.section.phase.template.org.funder? %> - <% suggested_answer = question.get_suggested_answer(current_user.org_id) %> - <% if !suggested_answer.nil? && suggested_answer.text != "" %> + <% example_answer = question.get_example_answer(current_user.org_id) %> + <% if example_answer.present? && example_answer.text.present? %> - <% if suggested_answer.is_example? %> - <%= _('Example of answer')%> - <% else %> - <%= _('Suggested answer')%> - <% end %> + <%= _('Example of answer')%> - <%= raw suggested_answer.text %> + <%= raw example_answer.text %> <% end %> <% end %> - <% if !question.guidance.nil? %> + <% guidance = question.get_guidance_annotation(current_user.org_id) %> + <% if guidance.present? %> <%= _('Guidance')%> - <%= raw question.guidance %> + <%= raw guidance.text %> <% end %> @@ -104,17 +101,17 @@
<% if !question.modifiable %> - <% suggested_answer = question.get_suggested_answer(current_user.org_id) %> - <% if !suggested_answer.nil? && suggested_answer.text != "" %> + <% example_answer = question.get_example_answer(current_user.org_id) %> + <% if example_answer.present? && example_answer.text.present? %>
- <%= render partial: 'suggested_answers/show_suggested_answer', locals: {suggested_answer: suggested_answer, question: question} %> + <%= render partial: 'annotations/show_annotation', locals: {annotation: example_answer, question: question} %>
<% end %> <% end %> @@ -129,12 +126,12 @@ confirm: _("You are about to delete '%{question_text}'. Are you sure?") % { :question_text => question.text }, method: :delete, class: "btn btn-primary"%>
<% elsif !@edit && question.modifiable %> - <% suggested_answer = question.get_suggested_answer(current_user.org_id) %> - <% if suggested_answer.nil? %> + <% example_answer = question.get_example_answer(current_user.org_id) %> + <% if example_answer.nil? %>
<%= hidden_field_tag :question_id, question.id, class: "question_id" %> - <%= link_to _('Add suggested answer/ example'), '# ', class: "btn btn-primary add_suggested_answer_button"%> + <%= link_to _('Add example answer'), '# ', class: "btn btn-primary add_suggested_answer_button"%>
<% end %> diff --git a/app/views/suggested_answers/_add_suggested_answer.html.erb b/app/views/suggested_answers/_add_suggested_answer.html.erb deleted file mode 100644 index fa5a8bf..0000000 --- a/app/views/suggested_answers/_add_suggested_answer.html.erb +++ /dev/null @@ -1,25 +0,0 @@ - -<%= form_for :suggested_answer, url: admin_create_suggested_answer_path do |f| %> - <%= f.hidden_field :org_id, value: current_user.org_id %> - <%= f.hidden_field :question_id, value: question.id %> - - - - - - -
<%= _('Suggested answer/ Example')%> -
    -
  • <%= f.select :is_example, {_('Example of answer') => true, _('Suggested answer') => false} %>
  • -
  • <%= f.text_area :text, rows: 5 %> -
  • -
-
-
- - -
- <%= f.submit _('Save'), class: "btn btn-primary" %> - <%= link_to _('Cancel'), "#", id: "cancel_suugested_answer", class: "btn cancel" %> -
-<%end%> diff --git a/app/views/suggested_answers/_edit_suggested_answer.html.erb b/app/views/suggested_answers/_edit_suggested_answer.html.erb deleted file mode 100644 index f0d92b7..0000000 --- a/app/views/suggested_answers/_edit_suggested_answer.html.erb +++ /dev/null @@ -1,26 +0,0 @@ - -<%= form_for(suggested_answer, url: admin_update_suggested_answer_path(suggested_answer), html: { method: :put}) do |f| %> - <%= f.hidden_field :org_id, value: current_user.org_id %> - - - - - - -
<%= _('Suggested answer/ Example')%> -
    -
  • <%= f.select :is_example, {_('Example of answer') => true, _('Suggested answer') => false} %>
  • -
  • <%= f.text_area :text, rows: 5 %>
  • -
-
-
- - -
- <%= f.submit _('Save'), class: 'btn btn-primary' %> - <%= link_to _('Delete'), admin_destroy_suggested_answer_path(id: suggested_answer.id), - confirm: _("You are about to delete a suggested answer/ example for '%{question_text}'. Are you sure?") % { :question_text => question.text }, method: :delete, class: "btn btn-primary"%> - <%= hidden_field_tag :question_id, question.id, class: "question_id" %> - <%= link_to _('Cancel'), '#', class: 'btn cancel cancel_edit_suggested_answer' %> -
-<% end %> diff --git a/app/views/suggested_answers/_show_suggested_answer.html.erb b/app/views/suggested_answers/_show_suggested_answer.html.erb deleted file mode 100644 index 5d04606..0000000 --- a/app/views/suggested_answers/_show_suggested_answer.html.erb +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - -
- <% if suggested_answer.is_example? then %> - <%= _('Example of answer')%> - <% else %> - <%= _('Suggested answer')%> - <% end %> - <%= raw suggested_answer.text %>
-
- -
- <%= hidden_field_tag :question_id, question.id, class: "question_id" %> - <%= link_to _('Edit suggested answer/ example'), '# ', class: "btn btn-primary edit_form_for_suggested_answer"%> -
diff --git a/app/views/templates/_edit_annotations.html.erb b/app/views/templates/_edit_annotations.html.erb index 96e7708..d388f61 100644 --- a/app/views/templates/_edit_annotations.html.erb +++ b/app/views/templates/_edit_annotations.html.erb @@ -44,19 +44,17 @@ - <%= _('Suggested answer/ Example')%> + <%= _('Example of Answer')%>
- <% suggested_answer = question.suggested_answers.find_by_org_id(current_user.org.id) %> - <% if suggested_answer.nil? %> - <% suggested_answer = question.suggested_answers.build %> + <% annotations = question.annotations.where(org_id: current_user.org_id).where('type <> ?',Annotation.types[:example_answer]).order(:created_at).first %> + <% if annotations.nil? %> + <% annotations = question.annotations.build %> <% end %> - <%= f.fields_for :suggested_answers, suggested_answer do |s|%> + <%= f.fields_for :annotations, annotation do |s|%> <%= s.hidden_field :org_id, value: current_user.org.id %>
    -
  • <%= s.select :is_example, {_('Example of answer') => true, _('Suggested answer') => false} %>
  • -
  • <%= s.text_area :text, rows: 5 %> -
  • +
  • <%= s.text_area :text, rows: 5 %>
<% end %>
diff --git a/config/routes.rb b/config/routes.rb index c09d22f..27c1d67 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -12,7 +12,7 @@ resources :questions resources :question_formats resources :question_options - resources :suggested_answers + resources :annotations resources :answers resources :guidances resources :guidance_groups @@ -161,7 +161,7 @@ end end - resources :suggested_answers, path: 'org/admin/templates/suggested_answers', only: [] do + resources :annotations, path: 'org/admin/templates/annotations', only: [] do member do post 'admin_create' put 'admin_update' diff --git a/db/schema.rb b/db/schema.rb index fe00e7b..f0bfbd2 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -16,6 +16,15 @@ # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" + create_table "annotations", force: :cascade do |t| + t.integer "question_id" + t.integer "org_id" + t.text "text" + t.integer "type", default: 0, null: false + t.datetime "created_at" + t.datetime "updated_at" + end + create_table "answers", force: :cascade do |t| t.text "text" t.integer "plan_id" @@ -271,15 +280,6 @@ t.datetime "updated_at", null: false end - create_table "suggested_answers", force: :cascade do |t| - t.integer "question_id" - t.integer "org_id" - t.text "text" - t.boolean "is_example" - t.datetime "created_at" - t.datetime "updated_at" - end - create_table "templates", force: :cascade do |t| t.string "title" t.text "description" @@ -330,8 +330,8 @@ t.string "email", default: "", null: false t.string "orcid_id" t.string "shibboleth_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at" + t.datetime "updated_at" t.string "encrypted_password", default: "" t.string "reset_password_token" t.datetime "reset_password_sent_at" @@ -370,6 +370,8 @@ add_index "users_perms", ["user_id", "perm_id"], name: "index_users_perms_on_user_id_and_perm_id", using: :btree + add_foreign_key "annotations", "orgs" + add_foreign_key "annotations", "questions" add_foreign_key "answers", "plans" add_foreign_key "answers", "questions" add_foreign_key "answers", "users" @@ -395,8 +397,6 @@ add_foreign_key "roles", "plans" add_foreign_key "roles", "users" add_foreign_key "sections", "phases" - add_foreign_key "suggested_answers", "orgs" - add_foreign_key "suggested_answers", "questions" add_foreign_key "templates", "orgs" add_foreign_key "themes_in_guidance", "guidances" add_foreign_key "themes_in_guidance", "themes" diff --git a/db/seeds.rb b/db/seeds.rb index 9277a5a..7da10a5 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -671,17 +671,17 @@ # Create suggested answers for a few questions # ------------------------------------------------------- -suggested_answers = [ +annotations = [ {text: "We will preserve it in Dryad or a similar data repository service.", - is_example: true, + type: Annotation.types[:example_answer], org: Org.find_by(abbreviation: 'GA'), question: Question.find_by(text: "What is your policy for long term access to your dataset?")}, {text: "We recommend that you identify the type(s) of content as well as the type of file(s) involved", - is_example: false, + type: Annotation.types[:example_answer], org: Org.find_by(abbreviation: 'GA'), question: Question.find_by(text: "What types of data will you collect and how will it be stored?")}, ] -suggested_answers.map{ |s| SuggestedAnswer.create!(s) if SuggestedAnswer.find_by(text: s[:text]).nil? } +annotations.map{ |s| Annotation.create!(s) if Annotation.find_by(text: s[:text]).nil? } # Create options for the dropdown, multi-select and radio buttons # ------------------------------------------------------- diff --git a/lib/tasks/migrate.rake b/lib/tasks/migrate.rake index cc9e87e..0bd54fd 100644 --- a/lib/tasks/migrate.rake +++ b/lib/tasks/migrate.rake @@ -248,5 +248,22 @@ end end end + + desc "enforce single published version for templates" + task single_published_template: :environment do + # for each group of versions of a template + Template.all.pluck(:dmptemplate_id).uniq.each do |dmptemplate_id| + published = false + Template.where(dmptemplate_id: dmptemplate_id).order(version: :desc).each do |template| + # leave the first published template we find alone + if !published && template.published + published = true + elsif published && template.published + template.published = false + template.save! + end + end + end + end end diff --git a/test/functional/annotations_controller_test.rb b/test/functional/annotations_controller_test.rb new file mode 100644 index 0000000..8615d16 --- /dev/null +++ b/test/functional/annotations_controller_test.rb @@ -0,0 +1,116 @@ +require 'test_helper' + +class AnnotationsControllerTest < ActionDispatch::IntegrationTest + + include Devise::Test::IntegrationHelpers + + setup do + @question = Annotation.first.question + + # Get the first Org Admin + scaffold_org_admin(@question.section.phase.template.org) + end + +# TODO: The following methods SHOULD replace the old 'admin_' prefixed methods. The routes file already has +# these defined. They are defined multiple times though and we need to clean this up! In particular +# look at the unnamed routes after 'new_plan_phase' below. They are not named because they are duplicates. +# We should just have: +# +# SHOULD BE: +# -------------------------------------------------- +# suggested_answers GET /templates/:template_id/phases/:phase_id/sections/:section_id/questions/:id sections#index +# POST /templates/:template_id/phases/:phase_id/sections/:section_id/questions/:id sections#create +# suggested_answer GET /templates/:template_id/phases/:phase_id/sections/:section_id/questions/:question_id/suggested_answer/:id sections#show +# PATCH /templates/:template_id/phases/:phase_id/section/:section_id/questions/:question_id/suggested_answer/:id sections#update +# PUT /templates/:template_id/phases/:phase_id/section/:section_id/questions/:question_id/suggested_answer/:id sections#update +# DELETE /templates/:template_id/phases/:phase_id/section/:section_id/questions/:question_id/suggested_answer/:id sections#destroy +# +# CURRENT RESULTS OF `rake routes` +# -------------------------------------------------- +# admin_create_suggested_answer POST /org/admin/templates/suggested_answers/:id/admin_create suggested_answers#admin_create +# admin_update_suggested_answer PUT /org/admin/templates/suggested_answers/:id/admin_update suggested_answers#admin_update +# admin_destroy_suggested_answer DELETE /org/admin/templates/suggested_answers/:id/admin_destroy suggested_answers#admin_destroy + + + + # POST /org/admin/templates/suggested_answers/:id/admin_create (admin_create_annotation_path) + # ---------------------------------------------------------- + test "create a new annotation" do + params = {org_id: @user.org.id, question_id: @question.id, text: "Here's a suggestion"} + + # Should redirect user to the root path if they are not logged in! + post admin_create_annotation_path(@question.id), {annotation: params} + assert_unauthorized_redirect_to_root_path + + sign_in @user + + post admin_create_annotation_path(@question.id), {annotation: params} + assert_response :redirect + assert_redirected_to "#{admin_show_phase_path(@question.section.phase.id)}?edit=true&question_id=#{@question.id}§ion_id=#{@question.section.id}" + assert_equal _('Information was successfully created.'), flash[:notice] + assert_equal "Here's a suggestion", Annotation.last.text, "expected the record to have been created!" + assert assigns(:example_answer) + + # Invalid object + post admin_create_annotation_path(@question.id), {annotation: {question_id: @question.id}} + assert flash[:notice].starts_with?(_('Could not create your')) + assert_response :success + assert assigns(:example_answer) + end + + # PUT /org/admin/templates/suggested_answers/:id/admin_update (admin_update_suggested_answer_path) + # ---------------------------------------------------------- + test "update the annotation" do + params = {text: 'UPDATE'} + + # Should redirect user to the root path if they are not logged in! + put admin_update_annotation_path(Annotation.first), {annotation: params} + assert_unauthorized_redirect_to_root_path + + sign_in @user + + # Valid save + put admin_update_annotation_path(Annotation.first), {annotation: params} + assert_equal _('Information was successfully updated.'), flash[:notice] + assert_response :redirect + assert_redirected_to "#{admin_show_phase_path(@question.section.phase.id)}?edit=true&question_id=#{@question.id}§ion_id=#{@question.section.id}" + assert assigns(:example_answer) + assert assigns(:question) + assert assigns(:section) + assert assigns(:phase) + assert_equal 'UPDATE', Annotation.first.text, "expected the record to have been updated" + +# TODO: We need to add in validation checks on the model and reactivate this test + # Invalid save +# put admin_update_suggested_answer_path(SuggestedAnswer.first), {suggested_answer: {text: nil}} +# assert flash[:notice].starts_with?(_('Could not update your')) +# assert_response :success +# assert assigns(:suggested_answer) +# assert assigns(:question) +# assert assigns(:section) +# assert assigns(:phase) + end + + # DELETE /org/admin/templates/suggested_answers/:id/admin_destroy (admin_destroy_suggested_answer_path) + # ---------------------------------------------------------- + test "delete the section" do + id = Annotation.first.id + # Should redirect user to the root path if they are not logged in! + delete admin_destroy_annotation_path(id: id) + assert_unauthorized_redirect_to_root_path + + sign_in @user + + delete admin_destroy_annotation_path(id: id) + assert_equal _('Information was successfully deleted.'), flash[:notice] + assert_response :redirect + assert_redirected_to "#{admin_show_phase_path(@question.section.phase.id)}?edit=true§ion_id=#{@question.section.id}" + assert assigns(:question) + assert assigns(:section) + assert assigns(:phase) + assert_raise ActiveRecord::RecordNotFound do + Annotation.find(id).nil? + end + end + +end \ No newline at end of file diff --git a/test/functional/questions_controller_test.rb b/test/functional/questions_controller_test.rb index 2a9cbcf..9a156f5 100644 --- a/test/functional/questions_controller_test.rb +++ b/test/functional/questions_controller_test.rb @@ -38,7 +38,7 @@ # POST /org/admin/templates/questions/:id/admin_create (admin_create_question_path) # ---------------------------------------------------------- test "create a new question" do - params = {section_id: @section.id, text: 'Test Question', number: 9, question_format_id: @question_format.id} + params = {section_id: @section.id, text: 'Test Question', number: 9, question_format_id: @question_format.id, annotations_attributes: {0 => {text: "some text", org_id: Org.first.id}}} @section.phase.template.dirty = false @section.phase.template.save! @@ -48,7 +48,11 @@ assert_unauthorized_redirect_to_root_path sign_in @user - + @new_question = Question.new + @new_question.number = @section.questions.count + 1 + example_answer = @new_question.annotations.build + example_answer.type = :example_answer + example_answer.save post admin_create_question_path(@section), {question: params} assert_response :redirect assert assigns(:question) diff --git a/test/functional/suggested_answers_controller_test.rb b/test/functional/suggested_answers_controller_test.rb deleted file mode 100644 index dcdd2ce..0000000 --- a/test/functional/suggested_answers_controller_test.rb +++ /dev/null @@ -1,116 +0,0 @@ -require 'test_helper' - -class SuggestedAnswersControllerTest < ActionDispatch::IntegrationTest - - include Devise::Test::IntegrationHelpers - - setup do - @question = SuggestedAnswer.first.question - - # Get the first Org Admin - scaffold_org_admin(@question.section.phase.template.org) - end - -# TODO: The following methods SHOULD replace the old 'admin_' prefixed methods. The routes file already has -# these defined. They are defined multiple times though and we need to clean this up! In particular -# look at the unnamed routes after 'new_plan_phase' below. They are not named because they are duplicates. -# We should just have: -# -# SHOULD BE: -# -------------------------------------------------- -# suggested_answers GET /templates/:template_id/phases/:phase_id/sections/:section_id/questions/:id sections#index -# POST /templates/:template_id/phases/:phase_id/sections/:section_id/questions/:id sections#create -# suggested_answer GET /templates/:template_id/phases/:phase_id/sections/:section_id/questions/:question_id/suggested_answer/:id sections#show -# PATCH /templates/:template_id/phases/:phase_id/section/:section_id/questions/:question_id/suggested_answer/:id sections#update -# PUT /templates/:template_id/phases/:phase_id/section/:section_id/questions/:question_id/suggested_answer/:id sections#update -# DELETE /templates/:template_id/phases/:phase_id/section/:section_id/questions/:question_id/suggested_answer/:id sections#destroy -# -# CURRENT RESULTS OF `rake routes` -# -------------------------------------------------- -# admin_create_suggested_answer POST /org/admin/templates/suggested_answers/:id/admin_create suggested_answers#admin_create -# admin_update_suggested_answer PUT /org/admin/templates/suggested_answers/:id/admin_update suggested_answers#admin_update -# admin_destroy_suggested_answer DELETE /org/admin/templates/suggested_answers/:id/admin_destroy suggested_answers#admin_destroy - - - - # POST /org/admin/templates/suggested_answers/:id/admin_create (admin_create_suggested_answer_path) - # ---------------------------------------------------------- - test "create a new section" do - params = {org_id: @user.org.id, question_id: @question.id, text: "Here's a suggestion"} - - # Should redirect user to the root path if they are not logged in! - post admin_create_suggested_answer_path(@question.id), {suggested_answer: params} - assert_unauthorized_redirect_to_root_path - - sign_in @user - - post admin_create_suggested_answer_path(@question.id), {suggested_answer: params} - assert_response :redirect - assert_redirected_to "#{admin_show_phase_path(@question.section.phase.id)}?edit=true&question_id=#{@question.id}§ion_id=#{@question.section.id}" - assert_equal _('Information was successfully created.'), flash[:notice] - assert_equal "Here's a suggestion", SuggestedAnswer.last.text, "expected the record to have been created!" - assert assigns(:suggested_answer) - - # Invalid object - post admin_create_suggested_answer_path(@question.id), {suggested_answer: {question_id: @question.id}} - assert flash[:notice].starts_with?(_('Could not create your')) - assert_response :success - assert assigns(:suggested_answer) - end - - # PUT /org/admin/templates/suggested_answers/:id/admin_update (admin_update_suggested_answer_path) - # ---------------------------------------------------------- - test "update the section" do - params = {text: 'UPDATE'} - - # Should redirect user to the root path if they are not logged in! - put admin_update_suggested_answer_path(SuggestedAnswer.first), {suggested_answer: params} - assert_unauthorized_redirect_to_root_path - - sign_in @user - - # Valid save - put admin_update_suggested_answer_path(SuggestedAnswer.first), {suggested_answer: params} - assert_equal _('Information was successfully updated.'), flash[:notice] - assert_response :redirect - assert_redirected_to "#{admin_show_phase_path(@question.section.phase.id)}?edit=true&question_id=#{@question.id}§ion_id=#{@question.section.id}" - assert assigns(:suggested_answer) - assert assigns(:question) - assert assigns(:section) - assert assigns(:phase) - assert_equal 'UPDATE', SuggestedAnswer.first.text, "expected the record to have been updated" - -# TODO: We need to add in validation checks on the model and reactivate this test - # Invalid save -# put admin_update_suggested_answer_path(SuggestedAnswer.first), {suggested_answer: {text: nil}} -# assert flash[:notice].starts_with?(_('Could not update your')) -# assert_response :success -# assert assigns(:suggested_answer) -# assert assigns(:question) -# assert assigns(:section) -# assert assigns(:phase) - end - - # DELETE /org/admin/templates/suggested_answers/:id/admin_destroy (admin_destroy_suggested_answer_path) - # ---------------------------------------------------------- - test "delete the section" do - id = SuggestedAnswer.first.id - # Should redirect user to the root path if they are not logged in! - delete admin_destroy_suggested_answer_path(id: id) - assert_unauthorized_redirect_to_root_path - - sign_in @user - - delete admin_destroy_suggested_answer_path(id: id) - assert_equal _('Information was successfully deleted.'), flash[:notice] - assert_response :redirect - assert_redirected_to "#{admin_show_phase_path(@question.section.phase.id)}?edit=true§ion_id=#{@question.section.id}" - assert assigns(:question) - assert assigns(:section) - assert assigns(:phase) - assert_raise ActiveRecord::RecordNotFound do - SuggestedAnswer.find(id).nil? - end - end - -end \ No newline at end of file diff --git a/test/unit/annotation_test.rb b/test/unit/annotation_test.rb new file mode 100644 index 0000000..9734c10 --- /dev/null +++ b/test/unit/annotation_test.rb @@ -0,0 +1,63 @@ +require 'test_helper' + +class AnnotationTest < ActiveSupport::TestCase + + setup do + scaffold_template + + @org = Org.last + @question = @template.phases.first.sections.first.questions.first + + @annotation = Annotation.create(org: @org, question: @question, text: 'Test', + type: Annotation.types[:example_answer]) + end + + # --------------------------------------------------- + test "required fields are required" do + assert_not Annotation.new.valid? + assert_not Annotation.new(org: @org, text: 'Tester').valid?, "expected the 'question' field to be required" + assert_not Annotation.new(question: @question, text: 'Tester').valid?, "expected the 'org' field to be required" + + # TODO: introduce validation on the model that requires text to be provided. + #assert_not Annotation.new(org: @org, question: @question).valid?, "expected the 'text' field to be required" + + # Ensure the bare minimum and complete versions are valid + a = Annotation.new(org: @org, question: @question, text: 'Tester') + assert a.valid?, "expected the 'org', 'question' and 'text' fields to be enough to create an Annotation! - #{a.errors.map{|f, m| f.to_s + ' ' + m}.join(', ')}" + end + + # --------------------------------------------------- + test "to_s returns the text" do + assert_equal @annotation.text, @annotation.to_s + end + + # --------------------------------------------------- + test "deep_copy" do + verify_deep_copy(@annotation, ['id', 'created_at', 'updated_at']) + end + + # --------------------------------------------------- + test "can CRUD Annotation" do + obj = Annotation.create(org: @org, question: @question, text: 'Tester') + assert_not obj.id.nil?, "was expecting to be able to create a new Annotation: #{obj.errors.map{|f, m| f.to_s + ' ' + m}.join(', ')}" + + obj.text = 'my tester' + obj.save! + obj.reload + assert_equal 'my tester', obj.text, "Was expecting to be able to update the text of the Annotation!" + + assert obj.destroy!, "Was unable to delete the Annotation!" + end + + # --------------------------------------------------- + test "can manage belongs_to relationship with Org" do + annotation = Annotation.new(question: @question, text: 'Testing') + verify_belongs_to_relationship(annotation, @org) + end + + # --------------------------------------------------- + test "can manage belongs_to relationship with Question" do + annotation = Annotation.new(org: @org, text: 'Testing') + verify_belongs_to_relationship(annotation, @question) + end +end \ No newline at end of file diff --git a/test/unit/org_test.rb b/test/unit/org_test.rb index c2c497d..3e7fd34 100644 --- a/test/unit/org_test.rb +++ b/test/unit/org_test.rb @@ -181,9 +181,9 @@ end # --------------------------------------------------- - test "can manage has_many relationship with SuggestedAnswers" do - sa = SuggestedAnswer.new(question: Question.first, text: 'Test Suggested Answer') - verify_has_many_relationship(@org, sa, @org.suggested_answers.count) + test "can manage has_many relationship with Annotations" do + a = Annotation.new(question: Question.first, text: 'Test Annotation') + verify_has_many_relationship(@org, a, @org.annotations.count) end # --------------------------------------------------- diff --git a/test/unit/question_test.rb b/test/unit/question_test.rb index be8981e..a5bb6c3 100644 --- a/test/unit/question_test.rb +++ b/test/unit/question_test.rb @@ -4,18 +4,18 @@ setup do @user = User.last - + scaffold_template - + @section = @template.phases.first.sections.first - + @question = Question.create(text: 'Test question', default_value: 'ABCD', guidance: 'Hello', - number: 999, section: @section, - question_format: QuestionFormat.where(option_based: false).first, + number: 999, section: @section, + question_format: QuestionFormat.where(option_based: false).first, option_comment_display: true, modifiable: true, - themes: [Theme.first], - suggested_answers: [SuggestedAnswer.new(org: @user.org, - text: "just a suggestion")]) + themes: [Theme.first], + annotations: [Annotation.new(org: @user.org, + text: "just a suggestion")]) end # --------------------------------------------------- @@ -24,21 +24,21 @@ assert_not Question.new(section: @section, number: 7).valid?, "expected the 'text' field to be required" assert_not Question.new(number: 7, text: 'Testing').valid?, "expected the 'section' field to be required" assert_not Question.new(section: @section, text: 'Testing').valid?, "expected the 'number' field to be required" - + # Ensure the bar minimum and complete versions are valid a = Question.new(section: @section, text: 'Testing', number: 7) assert a.valid?, "expected the 'text', 'section' and 'number' fields to be enough to create an Question! - #{a.errors.map{|f, m| f.to_s + ' ' + m}.join(', ')}" end - + # --------------------------------------------------- test "to_s returns the Question text" do assert_equal @question.text, @question.to_s end - + # --------------------------------------------------- test "returns the correct themed guidance for the org" do all = Theme.first.guidances + Theme.last.guidances - + # Attach 2 themes to the question @question.themes = [Theme.first, Theme.last] @question.save! @@ -53,25 +53,25 @@ assert @question.guidance_for_org(@user.org).first.first.include?(Theme.first.guidances.first.guidance_group.name), "expected the guidance_group.name" assert_equal Theme.first.guidances.first, @question.guidance_for_org(@user.org).first.last, "expected the guidance object to be returned" end - + # --------------------------------------------------- - test "returns the correct suggested answer for the org" do - @question.suggested_answers = [SuggestedAnswer.new(org: @user.org, text: 'Test 1', is_example: false), - SuggestedAnswer.new(org: Org.first, text: 'Test 2', is_example: false)] + test "returns the correct annotation for the org" do + @question.annotations = [Annotation.create(org: @user.org, text: 'Test 1', type: Annotation.types[:example_answer]), + Annotation.create(org: Org.first, text: 'Test 2', type: Annotation.types[:example_answer])] @question.save! - - assert_equal 'Test 1', @question.get_suggested_answer(@user.org.id).text, "expected the correct suggested answer" - assert_equal 'Test 2', @question.get_suggested_answer(Org.first.id).text, "expected the correct suggested answer" - + + assert_equal 'Test 1', @question.annotations.where(org_id: @user.org.id).first.text, "expected the correct annotation" + assert_equal 'Test 2', @question.annotations.where(org_id: Org.first.id).first.text, "expected the correct annotation" + org = Org.create(name: 'New One') - assert_equal nil, @question.get_suggested_answer(org.id), "expected no suggested answer for a new org" + assert_equal nil, @question.get_example_answer(org.id), "expected no annotation for a new org" end - + # --------------------------------------------------- test "deep copy" do verify_deep_copy(@question, ['id', 'created_at', 'updated_at']) end - + # --------------------------------------------------- test "can CRUD Question" do obj = Question.create(section: @section, text: 'Test ABC', number: 7) @@ -81,39 +81,39 @@ obj.save! obj.reload assert_equal 'Testing an update', obj.text, "Was expecting to be able to update the text of the Question!" - + assert obj.destroy!, "Was unable to delete the Question!" end - + # --------------------------------------------------- test "can manage belongs_to relationship with Section" do verify_belongs_to_relationship(@question, @template.phases.first.sections.last) end - + # --------------------------------------------------- test "can manage belongs_to relationship with QuestionFormat" do verify_belongs_to_relationship(@question, QuestionFormat.where(option_based: false).last) end - + # --------------------------------------------------- test "can manage has_many relationship with Answer" do scaffold_plan a = Answer.new(user: @user, plan: @plan, text: 'Test Answer') verify_has_many_relationship(@question, a, @question.answers.count) end - + # --------------------------------------------------- test "can manage has_many relationship with QuestionOption" do qo = QuestionOption.new(text: 'Test', number: 9) verify_has_many_relationship(@question, qo, @question.question_options.count) end - + # --------------------------------------------------- - test "can manage has_many relationship with SuggestedAnswer" do - sa = SuggestedAnswer.new(text: 'Suggested Answer', org: @user.org) - verify_has_many_relationship(@question, sa, @question.suggested_answers.count) + test "can manage has_many relationship with Annotation" do + sa = Annotation.new(text: 'Suggested Answer', org: @user.org) + verify_has_many_relationship(@question, sa, @question.annotations.count) end - + # --------------------------------------------------- test "can manage has_many relationship with Themes" do t = Theme.new(title: 'Test Theme') diff --git a/test/unit/suggested_answer_test.rb b/test/unit/suggested_answer_test.rb deleted file mode 100644 index 31be604..0000000 --- a/test/unit/suggested_answer_test.rb +++ /dev/null @@ -1,63 +0,0 @@ -require 'test_helper' - -class SuggestedAnswerTest < ActiveSupport::TestCase - - setup do - scaffold_template - - @org = Org.last - @question = @template.phases.first.sections.first.questions.first - - @suggested_answer = SuggestedAnswer.create(org: @org, question: @question, text: 'Test', - is_example: true) - end - - # --------------------------------------------------- - test "required fields are required" do - assert_not SuggestedAnswer.new.valid? - assert_not SuggestedAnswer.new(org: @org, text: 'Tester').valid?, "expected the 'question' field to be required" - assert_not SuggestedAnswer.new(question: @question, text: 'Tester').valid?, "expected the 'org' field to be required" - - # TODO: introduce validation on the model that requires text to be provided. - #assert_not SuggestedAnswer.new(org: @org, question: @question).valid?, "expected the 'text' field to be required" - - # Ensure the bare minimum and complete versions are valid - a = SuggestedAnswer.new(org: @org, question: @question, text: 'Tester') - assert a.valid?, "expected the 'org', 'question' and 'text' fields to be enough to create an SuggestedAnswer! - #{a.errors.map{|f, m| f.to_s + ' ' + m}.join(', ')}" - end - - # --------------------------------------------------- - test "to_s returns the text" do - assert_equal @suggested_answer.text, @suggested_answer.to_s - end - - # --------------------------------------------------- - test "deep_copy" do - verify_deep_copy(@suggested_answer, ['id', 'created_at', 'updated_at']) - end - - # --------------------------------------------------- - test "can CRUD SuggestedAnswer" do - obj = SuggestedAnswer.create(org: @org, question: @question, text: 'Tester') - assert_not obj.id.nil?, "was expecting to be able to create a new SuggestedAnswer: #{obj.errors.map{|f, m| f.to_s + ' ' + m}.join(', ')}" - - obj.text = 'my tester' - obj.save! - obj.reload - assert_equal 'my tester', obj.text, "Was expecting to be able to update the text of the SuggestedAnswer!" - - assert obj.destroy!, "Was unable to delete the SuggestedAnswer!" - end - - # --------------------------------------------------- - test "can manage belongs_to relationship with Org" do - suggested_answer = SuggestedAnswer.new(question: @question, text: 'Testing') - verify_belongs_to_relationship(suggested_answer, @org) - end - - # --------------------------------------------------- - test "can manage belongs_to relationship with Question" do - suggested_answer = SuggestedAnswer.new(org: @org, text: 'Testing') - verify_belongs_to_relationship(suggested_answer, @question) - end -end \ No newline at end of file