diff --git a/app/controllers/answers_controller.rb b/app/controllers/answers_controller.rb index e16f81b..f85c4dd 100644 --- a/app/controllers/answers_controller.rb +++ b/app/controllers/answers_controller.rb @@ -4,42 +4,50 @@ ## # POST /answers - # current implimentation creates a new answer each time one is submitted - # - # Probably should rename from from create to update - # Maybe better to just update the existing answer rather than generate a new - # one. Especiall since comments connect to answers - def create - # create a new answer based off the passed params - @answer = Answer.new(params[:answer]) - authorize @answer - # find the prevous answer to this question for this plan (created_at: "DESC").first - old_answer = @answer.plan.answer(@answer.question_id, false) - proceed = false - # confused why we are passing the text through like this if we have clearly passed the answer's other attr through plainly - # We can re-name it as it's defined in app/views/plans/_answer_form.html.erb - @answer.text = params["answer-text-#{@answer.question_id}".to_sym] - if (old_answer.nil? && @answer.text != "") || ((!old_answer.nil?) && (old_answer.text != @answer.text)) then - proceed = true - end - # Is this validation necissary? - if (@answer.question.question_format.title == I18n.t("helpers.checkbox") || - @answer.question.question_format.title == I18n.t("helpers.multi_select_box") || - @answer.question.question_format.title == I18n.t("helpers.radio_buttons") || - @answer.question.question_format.title == I18n.t("helpers.dropdown")) then - if (old_answer.nil? && @answer.option_ids.count > 0) || ((!old_answer.nil?) && (old_answer.option_ids - @answer.option_ids).count != 0 && (@answer.option_ids - old_answer.option_ids).count != 0) then - proceed = true - end - end - if proceed + def update + # create a new answer based off the passed params + logger.debug("RAY: update params=") + logger.debug params.inspect + + ans_params = params[:answer] + plan_id = ans_params[:plan_id] + user_id = ans_params[:user_id] + question_id = ans_params[:question_id] + @answer = Answer.find_by( + plan_id: plan_id, + user_id: user_id, + question_id: question_id) + logger.debug "RAY: found answer=#{@answer.inspect}" + if @answer.nil? + @answer = Answer.new(params[:answer]) + logger.debug "RAY: created answer=#{@answer.inspect}" + end + + authorize @answer + + @answer.text = params["answer-text-#{@answer.question_id}".to_sym] + + #TODO: check for optimistic locking + + # Is this validation necessary? +# if (@answer.question.question_format.title == I18n.t("helpers.checkbox") || +# @answer.question.question_format.title == I18n.t("helpers.multi_select_box") || +# @answer.question.question_format.title == I18n.t("helpers.radio_buttons") || +# @answer.question.question_format.title == I18n.t("helpers.dropdown")) then +# if (old_answer.nil? && @answer.option_ids.count > 0) || ((!old_answer.nil?) && (old_answer.option_ids - @answer.option_ids).count != 0 && (@answer.option_ids - old_answer.option_ids).count != 0) then +# proceed = true +# end +# end + +# if proceed if @answer.save redirect_to :back, status: :found, notice: I18n.t('helpers.project.answer_recorded') else redirect_to :back, notice: I18n.t('helpers.project.answer_error') end - else - redirect_to :back, notice: I18n.t('helpers.project.answer_no_change') - end +# else +# redirect_to :back, notice: I18n.t('helpers.project.answer_no_change') +# end end -end \ No newline at end of file +end diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb index 713dda5..a311c09 100644 --- a/app/controllers/home_controller.rb +++ b/app/controllers/home_controller.rb @@ -14,7 +14,7 @@ if name.blank? redirect_to edit_user_registration_path else - redirect_to projects_url + redirect_to plans_url end end end diff --git a/app/controllers/notes_controller.rb b/app/controllers/notes_controller.rb index 9ebd6d3..d116da0 100644 --- a/app/controllers/notes_controller.rb +++ b/app/controllers/notes_controller.rb @@ -5,19 +5,22 @@ ## # POST /notes def create - @note = Note.new(params[:new_note]) - @note.text = params["#{params[:new_note][:question_id]}new_note_text"] - @note.question_id = params[:new_note][:question_id] + @note = Note.new + logger.debug "RAY: into save note" @note.user_id = params[:new_note][:user_id] - @note.plan_id = params[:new_note][:plan_id] + @note.answer_id = params[:new_note][:answer_id] + @note.text = params["#{params[:new_note][:answer_id]}new_note_text"] + authorize @note - @plan = Plan.find(@note.plan_id) - @project = Project.find(@plan.project_id) + answer = Answer.find(@note.answer_id) + @plan = answer.plan + @phase = answer.question.section.phase + logger.debug "RAY: saving " + @note.inspect if @note.save - session[:question_id_notes] = @note.question_id - redirect_to edit_project_plan_path(@project, @plan), status: :found, notice: I18n.t("helpers.comments.note_created") + session[:question_id_notes] = answer.question_id + redirect_to edit_plan_phase_path(@plan, @phase), status: :found, notice: I18n.t("helpers.comments.note_created") end end diff --git a/app/controllers/phases_controller.rb b/app/controllers/phases_controller.rb new file mode 100644 index 0000000..5c08f41 --- /dev/null +++ b/app/controllers/phases_controller.rb @@ -0,0 +1,47 @@ +class PhasesController < ApplicationController + + after_action :verify_authorized + + TEXTAREA = QuestionFormat.where(title: "Text area").first.id + TEXTFIELD = QuestionFormat.where(title: "Text field").first.id + RADIO = QuestionFormat.where(title: "Radio buttons").first.id + CHECKBOX = QuestionFormat.where(title: "Check box").first.id + DROPDOWN = QuestionFormat.where(title: "Dropdown").first.id + MULTI = QuestionFormat.where(title: "Multi select box").first.id + + # GET /phases/1/edit + def edit + + @textarea = TEXTAREA + @textfield = TEXTFIELD + @radio = RADIO + @checkbox = CHECKBOX + @dropdown = DROPDOWN + @multi = MULTI + + @plan = Plan.find(params[:plan_id]) + authorize @plan + @phase = Phase.where(template_id: @plan.template_id, slug: params[:id]).first + + @sections = @phase.sections + @section_answers = Hash.new + @phase.sections.each do |section| + nanswers = 0 + questions = section.questions + questions.each do |q| + answers = q.answers.where(plan_id: @plan) + nanswers += answers.count + end + @section_answers[section.id] = nanswers + end + + if !user_signed_in? then + respond_to do |format| + format.html { redirect_to edit_user_registration_path } + end + end + + end + + +end diff --git a/app/controllers/plans_controller.rb b/app/controllers/plans_controller.rb index ba1f3ab..7cfde4d 100644 --- a/app/controllers/plans_controller.rb +++ b/app/controllers/plans_controller.rb @@ -1,208 +1,424 @@ class PlansController < ApplicationController - #Uncomment the line below in order to add authentication to this page - users without permission will not be able to add new plans - #load_and_authorize_resource + #Uncomment the line below in order to add authentication to this page - users without permission will not be able to add new plans + #load_and_authorize_resource after_action :verify_authorized - - # GET /plans/1/edit - def edit - @plan = Plan.find(params[:id]) + TEXTAREA = QuestionFormat.where(title: "Text area").first.id + TEXTFIELD = QuestionFormat.where(title: "Text field").first.id + RADIO = QuestionFormat.where(title: "Radio buttons").first.id + CHECKBOX = QuestionFormat.where(title: "Check box").first.id + DROPDOWN = QuestionFormat.where(title: "Dropdown").first.id + MULTI = QuestionFormat.where(title: "Multi select box").first.id + + def index + authorize Plan + @plans = current_user.plans + end + + + + # GET /plans/new + def new + if user_signed_in? then + @plan = Plan.new + authorize @plan + @funders = Org.funder.all + + respond_to do |format| + format.html # new.html.erb + end + else + respond_to do |format| + format.html { redirect_to edit_user_registration_path } + end + end + end + + + def create + if user_signed_in? then + @plan = Plan.new + authorize @plan + @plan.save + + funder_id = params[:plan][:funder_id] + if !funder_id.blank? + # get all funder @templates + funder = Org.find(params[:plan][:funder_id]) + logger.debug "RAY: funder = " + funder.inspect + @templates = get_most_recent( funder.templates.where("published = ?", true).all ) + logger.debug "RAY: found "+ @templates.count.to_s + " templates = " + @templates.inspect + + orgtemplates = current_user.org.templates.all + logger.debug "RAY: found "+ @templates.count.to_s + " org templates = " + @templates.inspect + replacements = [] + + # replace any that are customised by the org + orgtemplates.each do |orgt| + base_template = orgt.customization_of + @templates.delete(base_template) + replacements << orgt + end + @templates + replacements + logger.debug "RAY: finally "+ @templates.count.to_s + " templates = " + @templates.inspect + + else + # get all org @templates which are not customisations + @templates = current_user.org.templates.where(customization_of: nil) + + # if none of these get the basic dcc template + if @templates.blank? + @templates = Template.find_by_is_default(true) + end + end + + # if we have more than one template then back to the user + # using the 'create' template + # to choose otherwise just create the plan + # and go to the plan/show template + if @templates.length > 1 + return + end + + @plan.template = @templates[0] + + @plan.principal_investigator = current_user.name + + @plan.title = I18n.t('helpers.project.my_project_name')+' ('+@plan.template.title+')' + + @plan.assign_creator(current_user.id) + + @plan.set_possible_guidance_groups + + @selected_guidance_groups = @plan.guidance_groups.map{ |pgg| [pgg.name, pgg.id, :checked => false] } + @selected_guidance_groups.sort! + + respond_to do |format| + if @plan.save + #format.html { redirect_to({:action => "show", :id => @plan.slug, :show_form => "yes"}, {:notice => I18n.t('helpers.project.success')}) } + format.html { redirect_to({:action => "show", :id => @plan.id, :editing => true }, {:notice => I18n.t('helpers.project.success')}) } + else + @error = "Something went wrong" + format.html { render action: "new" } + end + end + else + render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) + end + end + + + + # GET /plans/show + def show + @plan = Plan.find(params[:id]) authorize @plan + @editing = params[:editing] && @plan.administerable_by?(current_user.id) + @selected_guidance_groups = [] + @selected_guidance_groups = @plan.plan_guidance_groups.map{ |pgg| [pgg.guidance_group.name, pgg.guidance_group.id, :checked => pgg.selected] } + @selected_guidance_groups.sort! + + if user_signed_in? && @plan.readable_by?(current_user.id) then + respond_to do |format| + format.html # show.html.erb + end + elsif user_signed_in? then + respond_to do |format| + format.html { redirect_to projects_url, notice: I18n.t('helpers.settings.plans.errors.no_access_account') } + end + else + respond_to do |format| + format.html { redirect_to edit_user_registration_path } + end + end + end + + + + # we can go into this with the user able to edit or not able to edit + # the same edit form gets rendered but then different partials get used + # to render the answers depending on whether it is readonly or not + # + # we may or may not have a phase param. + # if we have none then we are editing/displaying the plan details + # if we have a phase then we are editing that phase. + # + # GET /plans/1/edit + def edit + @textarea = TEXTAREA + @textfield = TEXTFIELD + @radio = RADIO + @checkbox = CHECKBOX + @dropdown = DROPDOWN + @multi = MULTI + + @plan = Plan.find(params[:id]) + + @phase = nil + if params[:phase] + @phase = Phase.find(params[:phase]) + end + + authorize @plan + @readonly = @plan.editable_by?(current_user.id) if !user_signed_in? then respond_to do |format| - format.html { redirect_to edit_user_registration_path } - end - elsif !@plan.readable_by(current_user.id) then - respond_to do |format| - format.html { redirect_to projects_url, notice: I18n.t('helpers.settings.plans.errors.no_access_account') } - end - end - end + format.html { redirect_to edit_user_registration_path } + end + elsif !@plan.readable_by?(current_user.id) then + respond_to do |format| + format.html { redirect_to projects_url, notice: I18n.t('helpers.settings.plans.errors.no_access_account') } + end + end + end - # PUT /plans/1 - # PUT /plans/1.json - def update - @plan = Plan.find(params[:id]) + # PUT /plans/1 + # PUT /plans/1.json + def update + @plan = Plan.find(params[:id]) authorize @plan - if user_signed_in? && @plan.editable_by(current_user.id) then - respond_to do |format| - if @plan.update_attributes(params[:plan]) - format.html { redirect_to @plan, notice: I18n.t('helpers.project.success_update') } - format.json { head :no_content } - else - format.html { render action: "edit" } - end - end - else - render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) - end - end + if user_signed_in? && @plan.editable_by?(current_user.id) then + respond_to do |format| + if @plan.update_attributes(params[:plan]) + format.html { redirect_to @plan, :editing => false, notice: I18n.t('helpers.project.success_update') } + format.json { head :no_content } + else + format.html { render action: "edit" } + end + end + else + render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) + end + end + + + + def update_guidance_choices + logger.debug "RAY: update_guidance_choices with params" + logger.debug params.inspect + + @plan = Plan.find(params[:id]) + authorize @plan + if user_signed_in? && @plan.editable_by?(current_user.id) then + guidance_ids = params[:plan][:guidances] + logger.debug "RAY: guidance ids = " + guidance_ids.inspect + @plan.plan_guidance_groups.each do |pgg| + logger.debug "RAY: looking at pgg = " + pgg.inspect + pgg.selected = guidance_ids.include?(pgg.guidance_group_id.to_s) + logger.debug "RAY: pg now = " + pgg.inspect + pgg.save! + end + @plan.save! + + respond_to do |format| + format.json { head :no_content } + end + else + render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) + end + end + + + + def destroy + @plan = Plan.find(params[:id]) + authorize @plan + if user_signed_in? && @plan.editable_by?(current_user.id) then + @plan.destroy + + respond_to do |format| + format.html { redirect_to plans_url } + end + else + render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) + end + end # GET /status/1.json - # only returns json, why is this here? + # only returns json, why is this here? def status - @plan = Plan.find(params[:id]) - authorize @plan - if user_signed_in? && @plan.readable_by(current_user.id) then - respond_to do |format| - format.json { render json: @plan.status } - end - else - render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) - end - end - - def section_answers - @plan = Plan.find(params[:id]) - authorize @plan - if user_signed_in? && @plan.readable_by(current_user.id) then - respond_to do |format| - format.json { render json: @plan.section_answers(params[:section_id]) } - end - else - render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) - end - end - - def locked - @plan = Plan.find(params[:id]) - authorize @plan - if !@plan.nil? && user_signed_in? && @plan.readable_by(current_user.id) then - respond_to do |format| - format.json { render json: @plan.locked(params[:section_id],current_user.id) } - end - else - render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) - end - end - - def delete_recent_locks - @plan = Plan.find(params[:id]) + @plan = Plan.find(params[:id]) authorize @plan - if user_signed_in? && @plan.editable_by(current_user.id) then - respond_to do |format| - if @plan.delete_recent_locks(current_user.id) - format.html { render action: "edit" } - else - format.html { render action: "edit" } - end - end - else - render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) - end - end + if user_signed_in? && @plan.readable_by(current_user.id) then + respond_to do |format| + format.json { render json: @plan.status } + end + else + render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) + end + end - def unlock_all_sections - @plan = Plan.find(params[:id]) + def section_answers + @plan = Plan.find(params[:id]) authorize @plan - if user_signed_in? && @plan.editable_by(current_user.id) then - respond_to do |format| - if @plan.unlock_all_sections(current_user.id) - format.html { render action: "edit" } - else - format.html { render action: "edit" } - end - end - else - render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) - end - end + if user_signed_in? && @plan.readable_by(current_user.id) then + respond_to do |format| + format.json { render json: @plan.section_answers(params[:section_id]) } + end + else + render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) + end + end - def lock_section - @plan = Plan.find(params[:id]) + def locked + @plan = Plan.find(params[:id]) authorize @plan - if user_signed_in? && @plan.editable_by(current_user.id) then - respond_to do |format| - if @plan.lock_section(params[:section_id], current_user.id) - format.html { render action: "edit" } - else - format.html { render action: "edit" } - format.json { render json: @plan.errors, status: :unprocessable_entity } - end - end - else - render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) - end - end + if !@plan.nil? && user_signed_in? && @plan.readable_by(current_user.id) then + respond_to do |format| + format.json { render json: @plan.locked(params[:section_id],current_user.id) } + end + else + render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) + end + end - def unlock_section - @plan = Plan.find(params[:id]) + def delete_recent_locks + @plan = Plan.find(params[:id]) authorize @plan - if user_signed_in? && @plan.editable_by(current_user.id) then - respond_to do |format| - if @plan.unlock_section(params[:section_id], current_user.id) - format.html { render action: "edit" } + if user_signed_in? && @plan.editable_by(current_user.id) then + respond_to do |format| + if @plan.delete_recent_locks(current_user.id) + format.html { render action: "edit" } + else + format.html { render action: "edit" } + end + end + else + render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) + end + end - else - format.html { render action: "edit" } - end - end - else - render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) - end - end + def unlock_all_sections + @plan = Plan.find(params[:id]) + authorize @plan + if user_signed_in? && @plan.editable_by(current_user.id) then + respond_to do |format| + if @plan.unlock_all_sections(current_user.id) + format.html { render action: "edit" } + else + format.html { render action: "edit" } + end + end + else + render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) + end + end - def answer - @plan = Plan.find(params[:id]) - authorize @plan - if user_signed_in? && @plan.readable_by(current_user.id) then - respond_to do |format| - format.json { render json: @plan.answer(params[:q_id], false).to_json(:include => :options) } - end - else - render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) - end - end + def lock_section + @plan = Plan.find(params[:id]) + authorize @plan + if user_signed_in? && @plan.editable_by(current_user.id) then + respond_to do |format| + if @plan.lock_section(params[:section_id], current_user.id) + format.html { render action: "edit" } + else + format.html { render action: "edit" } + format.json { render json: @plan.errors, status: :unprocessable_entity } + end + end + else + render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) + end + end - def export - @plan = Plan.find(params[:id]) + def unlock_section + @plan = Plan.find(params[:id]) + authorize @plan + if user_signed_in? && @plan.editable_by(current_user.id) then + respond_to do |format| + if @plan.unlock_section(params[:section_id], current_user.id) + format.html { render action: "edit" } + + else + format.html { render action: "edit" } + end + end + else + render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) + end + end + + def answer + @plan = Plan.find(params[:id]) + authorize @plan + if user_signed_in? && @plan.readable_by(current_user.id) then + respond_to do |format| + format.json { render json: @plan.answer(params[:q_id], false).to_json(:include => :options) } + end + else + render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) + end + end + + def export + @plan = Plan.find(params[:id]) authorize @plan - if (user_signed_in? && @plan.readable_by(current_user.id)) then - @exported_plan = ExportedPlan.new.tap do |ep| - ep.plan = @plan - ep.user = current_user ||= nil - #ep.format = request.format.try(:symbol) + if user_signed_in? && @plan.readable_by(current_user.id) then + @exported_plan = ExportedPlan.new.tap do |ep| + ep.plan = @plan + ep.user = current_user + #ep.format = request.format.try(:symbol) ep.format = request.format.to_sym - plan_settings = @plan.settings(:export) + plan_settings = @plan.settings(:export) - Settings::Dmptemplate::DEFAULT_SETTINGS.each do |key, value| - ep.settings(:export).send("#{key}=", plan_settings.send(key)) - end - end + Settings::Dmptemplate::DEFAULT_SETTINGS.each do |key, value| + ep.settings(:export).send("#{key}=", plan_settings.send(key)) + end + end - @exported_plan.save! # FIXME: handle invalid request types without erroring? - file_name = @exported_plan.project_name + @exported_plan.save! # FIXME: handle invalid request types without erroring? + file_name = @exported_plan.project_name - respond_to do |format| - format.html - format.xml - format.json - format.csv { send_data @exported_plan.as_csv, filename: "#{file_name}.csv" } - format.text { send_data @exported_plan.as_txt, filename: "#{file_name}.txt" } - format.docx { headers["Content-Disposition"] = "attachment; filename=\"#{file_name}.docx\""} - format.pdf do - @formatting = @plan.settings(:export).formatting - render pdf: file_name, - margin: @formatting[:margin], - footer: { - center: t('helpers.plan.export.pdf.generated_by'), - font_size: 8, - spacing: (@formatting[:margin][:bottom] / 2) - 4, - right: '[page] of [topage]' - } - end - end - - elsif !user_signed_in? then - respond_to do |format| - format.html { redirect_to edit_user_registration_path } - end - - elsif !@plan.editable_by(current_user.id) then - respond_to do |format| - format.html { redirect_to projects_url, notice: I18n.t('helpers.settings.plans.errors.no_access_account') } - end - end - end + respond_to do |format| + format.html + format.xml + format.json + format.csv { send_data @exported_plan.as_csv, filename: "#{file_name}.csv" } + format.text { send_data @exported_plan.as_txt, filename: "#{file_name}.txt" } + format.docx { headers["Content-Disposition"] = "attachment; filename=\"#{file_name}.docx\""} + format.pdf do + @formatting = @plan.settings(:export).formatting + render pdf: file_name, + margin: @formatting[:margin], + footer: { + center: t('helpers.plan.export.pdf.generated_by'), + font_size: 8, + spacing: (@formatting[:margin][:bottom] / 2) - 4, + right: '[page] of [topage]' + } + end + end + elsif !user_signed_in? then + respond_to do |format| + format.html { redirect_to edit_user_registration_path } + end + elsif !@plan.editable_by(current_user.id) then + respond_to do |format| + format.html { redirect_to projects_url, notice: I18n.t('helpers.settings.plans.errors.no_access_account') } + end + end + end + + + + private + + + def get_most_recent( templates ) + groups = Hash.new + templates.each do |t| + k = t.dmptemplate_id + if !groups.has_key?(k) + groups[k] =t + else + other = groups[k] + if other.version < t.version + groups[k] = t + end + end + end + groups.values + end + end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index f8fe2a8..1cb7c24 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -1,202 +1,186 @@ class ProjectsController < ApplicationController - before_filter :get_plan_list_columns, only: %i( index ) + before_filter :get_plan_list_columns, only: %i( index ) after_action :verify_authorized - # GET /projects - # GET /projects.json - def index + # GET /projects + # GET /projects.json + def index authorize Project ## TODO: Is this A magic String? the "Show_shib_link?" as we define it and users dont see cookies - if user_signed_in? then - if (current_user.shibboleth_id.nil? || current_user.shibboleth_id.length == 0) && !cookies[:show_shib_link].nil? && cookies[:show_shib_link] == "show_shib_link" then - flash.notice = "Would you like to #{view_context.link_to I18n.t('helpers.shibboleth_to_link_text'), user_omniauth_shibboleth_path}".html_safe - end + if user_signed_in? then + if (current_user.shibboleth_id.nil? || current_user.shibboleth_id.length == 0) && !cookies[:show_shib_link].nil? && cookies[:show_shib_link] == "show_shib_link" then + flash.notice = "Would you like to #{view_context.link_to I18n.t('helpers.shibboleth_to_link_text'), user_omniauth_shibboleth_path}".html_safe + end - @projects = current_user.projects.filter(params[:filter]) - @has_projects = current_user.projects.any? # unfiltered count + @projects = current_user.projects.filter(params[:filter]) + @has_projects = current_user.projects.any? # unfiltered count - respond_to do |format| - format.html # index.html.erb - end - else - respond_to do |format| - format.html { redirect_to edit_user_registration_path } - end - end - end - - # GET /projects/1 - # GET /projects/1.json - def show - @project = Project.find(params[:id]) - authorize @project - @show_form = false - if params[:show_form] == "yes" then - @show_form = true - end - if user_signed_in? && @project.readable_by(current_user.id) then - respond_to do |format| - format.html # show.html.erb - end - elsif user_signed_in? then - respond_to do |format| - format.html { redirect_to projects_url, notice: I18n.t('helpers.settings.plans.errors.no_access_account') } - end - else - respond_to do |format| - format.html { redirect_to edit_user_registration_path } - end - end - end - - # GET /projects/new - # GET /projects/new.json - def new - if user_signed_in? then - @project = Project.new - authorize @project - @project.organisation = current_user.organisation - @funders = orgs_of_type(constant("organisation_types.funder"), true) - @templates = get_available_templates - @guidance_groups = get_available_guidance - @always_guidance = get_always_available_guidance - @institutions = orgs_of_type(constant("organisation_types.institution")) - - # Replacing DB call in view with instance variable - @org_templates = current_user.org.templates - - respond_to do |format| - format.html # new.html.erb - end - else - respond_to do |format| - format.html { redirect_to edit_user_registration_path } - end - end - end - - # GET /projects/1/edit - # Should this be removed? - def edit - @project = Project.find(params[:id]) - authorize @project - if !user_signed_in? then - respond_to do |format| - format.html { redirect_to edit_user_registration_path } - end - elsif !@project.editable_by(current_user.id) then - respond_to do |format| - format.html { redirect_to projects_url, notice: I18n.t('helpers.settings.plans.errors.no_access_account') } - end - end - end - - def share - @project = Project.find(params[:id]) - authorize @project - if !user_signed_in? then - respond_to do |format| - format.html { redirect_to edit_user_registration_path } - end - elsif !@project.editable_by(current_user.id) then - respond_to do |format| - format.html { redirect_to projects_url, notice: I18n.t('helpers.settings.plans.errors.no_access_account') } - end - end - end - - def export - @project = Project.find(params[:id]) - authorize @project - if !user_signed_in? then - respond_to do |format| - format.html { redirect_to edit_user_registration_path } - end - else - respond_to do |format| - format.html { render action: "export" } - - end - end - end - - # POST /projects - # POST /projects.json - def create - if user_signed_in? then - - attrs = project_params - @project = Project.new(attrs) - authorize @project - - if @project.dmptemplate.nil? && attrs[:funder_id] != "" then # this shouldn't be necessary - see setter for funder_id in project.rb - funder = Organisation.find(attrs[:funder_id]) - if funder.dmptemplates.count == 1 then - @project.dmptemplate = funder.published_templates.first - end - - elsif @project.dmptemplate.nil? || params[:default_tag] == 'true' then - if @project.organisation.nil? || params[:default_tag] == 'true' || @project.organisation.published_templates.first.nil? then - @project.dmptemplate = Dmptemplate.find_by_is_default(true) + respond_to do |format| + format.html # index.html.erb + end else - @project.dmptemplate = @project.organisation.published_templates.first + respond_to do |format| + format.html { redirect_to edit_user_registration_path } + end end - end - @project.principal_investigator = current_user.name(false) - - @project.title = I18n.t('helpers.project.my_project_name')+' ('+@project.dmptemplate.title+')' - @project.assign_creator(current_user.id) - respond_to do |format| - if @project.save - format.html { redirect_to({:action => "show", :id => @project.slug, :show_form => "yes"}, {:notice => I18n.t('helpers.project.success')}) } - else - format.html { render action: "new" } - end - end - - else - render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) end - end - # PUT /projects/1 - # PUT /projects/1.json - def update - @project = Project.find(params[:id]) + # GET /projects/1 + # GET /projects/1.json + def show + @project = Project.find(params[:id]) authorize @project - - if user_signed_in? && @project.editable_by(current_user.id) then - attrs = project_params - - if @project.update_attributes(attrs) + @show_form = false + if params[:show_form] == "yes" then + @show_form = true + end + if user_signed_in? && @project.readable_by(current_user.id) then + respond_to do |format| + format.html # show.html.erb + end + elsif user_signed_in? then + respond_to do |format| + format.html { redirect_to projects_url, notice: I18n.t('helpers.settings.plans.errors.no_access_account') } + end + else + respond_to do |format| + format.html { redirect_to edit_user_registration_path } + end + end + end + + def new + if user_signed_in? then + @plan = Plan.new + authorize @plan + @funders = Org.funder.all + respond_to do |format| - format.html { redirect_to({:action => "show", :id => @project.slug, notice: I18n.t('helpers.project.success_update') }) } + format.html # new.html.erb end else respond_to do |format| - format.html { render action: "edit" } + format.html { redirect_to edit_user_registration_path } end end - else - render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) end - end - # DELETE /projects/1 - # DELETE /projects/1.json - def destroy - @project = Project.find(params[:id]) + + # GET /projects/1/edit + # Should this be removed? + def edit + @project = Project.find(params[:id]) authorize @project - if user_signed_in? && @project.editable_by(current_user.id) then - @project.destroy - - respond_to do |format| - format.html { redirect_to projects_url } - end - else - render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) + if !user_signed_in? then + respond_to do |format| + format.html { redirect_to edit_user_registration_path } + end + elsif !@project.editable_by(current_user.id) then + respond_to do |format| + format.html { redirect_to projects_url, notice: I18n.t('helpers.settings.plans.errors.no_access_account') } + end + end end - end + + def share + @project = Project.find(params[:id]) + authorize @project + if !user_signed_in? then + respond_to do |format| + format.html { redirect_to edit_user_registration_path } + end + elsif !@project.editable_by(current_user.id) then + respond_to do |format| + format.html { redirect_to projects_url, notice: I18n.t('helpers.settings.plans.errors.no_access_account') } + end + end + end + + def export + @project = Project.find(params[:id]) + authorize @project + if !user_signed_in? then + respond_to do |format| + format.html { redirect_to edit_user_registration_path } + end + else + respond_to do |format| + format.html { render action: "export" } + + end + end + end + + # POST /projects + def create + puts params + return + if user_signed_in? then + @plan = Plan.new(params[:plan]) + authorize @project + if @project.dmptemplate.nil? && params[:project][:funder_id] != "" then # this shouldn't be necessary - see setter for funder_id in project.rb + funder = Org.find(params[:project][:funder_id]) + if funder.dmptemplates.count == 1 then + @project.dmptemplate = funder.published_templates.first + end + elsif @project.dmptemplate.nil? || params[:default_tag] == 'true' then + if @project.organisation.nil? || params[:default_tag] == 'true' || @project.organisation.published_templates.first.nil? then + @project.dmptemplate = Dmptemplate.find_by_is_default(true) + else + @project.dmptemplate = @project.organisation.published_templates.first + end + end + @project.principal_investigator = current_user.name(false) + + @project.title = I18n.t('helpers.project.my_project_name')+' ('+@project.dmptemplate.title+')' + @project.assign_creator(current_user.id) + respond_to do |format| + if @project.save + format.html { redirect_to({:action => "show", :id => @project.slug, :show_form => "yes"}, {:notice => I18n.t('helpers.project.success')}) } + else + format.html { render action: "new" } + end + end + else + render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) + end + end + + # PUT /projects/1 + # PUT /projects/1.json + def update + @project = Project.find(params[:id]) + authorize @project + if user_signed_in? && @project.editable_by(current_user.id) then + if @project.update_attributes(params[:project]) + respond_to do |format| + format.html { redirect_to({:action => "show", :id => @project.slug, notice: I18n.t('helpers.project.success_update') }) } + end + else + respond_to do |format| + format.html { render action: "edit" } + end + end + else + render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) + end + end + + # DELETE /projects/1 + # DELETE /projects/1.json + def destroy + @project = Project.find(params[:id]) + authorize @project + if user_signed_in? && @project.editable_by(current_user.id) then + @project.destroy + + respond_to do |format| + format.html { redirect_to projects_url } + end + else + render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) + end + end # returns to AJAX call from frontend # difficult to secure as it passes through params, and dosent curate data based @@ -325,7 +309,7 @@ # ----------------------------------------------------------- def get_available_templates - Dmptemplate.where(published: true) + Template.find_by(published: true) end # ----------------------------------------------------------- diff --git a/app/helpers/phases_helper.rb b/app/helpers/phases_helper.rb new file mode 100644 index 0000000..610c227 --- /dev/null +++ b/app/helpers/phases_helper.rb @@ -0,0 +1,2 @@ +module PhasesHelper +end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 84c458d..e445a1a 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -68,7 +68,7 @@ # -------------------------------------------------------- def plan_settings_indicator(plan) plan_settings = plan.super_settings(:export) - template_settings = plan.project.dmptemplate.try(:settings, :export) + template_settings = plan.template.try(:settings, :export) key = if plan_settings.try(:value?) plan_settings.formatting == template_settings.formatting ? "template_formatting" : "custom_formatting" diff --git a/app/models/answer.rb b/app/models/answer.rb index ebc583c..35e0c2d 100644 --- a/app/models/answer.rb +++ b/app/models/answer.rb @@ -5,6 +5,7 @@ belongs_to :question belongs_to :user belongs_to :plan + has_many :notes, dependent: :destroy has_and_belongs_to_many :question_options, join_table: "answers_question_options" has_many :notes @@ -18,21 +19,21 @@ ## # Validations - validates :user, :plan, :question, presence: true - - # Make sure there is only one answer per question! - validates :question, uniqueness: {scope: [:plan], - message: I18n.t('helpers.answer.only_one_per_question')} - - # The answer MUST have a text value if the question is NOT option based or a question_option if - # it is option based. - validates :text, presence: true, if: Proc.new{|a| - (a.question.nil? ? false : !a.question.question_format.option_based?) - } - validates :question_options, presence: true, if: Proc.new{|a| - (a.question.nil? ? false : a.question.question_format.option_based?) - } - - # Make sure the plan and question are associated with the same template! - validates :plan, :question, answer_for_correct_template: true +# validates :user, :plan, :question, presence: true +# +# # Make sure there is only one answer per question! +# validates :question, uniqueness: {scope: [:plan], +# message: I18n.t('helpers.answer.only_one_per_question')} +# +# # The answer MUST have a text value if the question is NOT option based or a question_option if +# # it is option based. +# validates :text, presence: true, if: Proc.new{|a| +# (a.question.nil? ? false : !a.question.question_format.option_based?) +# } +# validates :question_options, presence: true, if: Proc.new{|a| +# (a.question.nil? ? false : a.question.question_format.option_based?) +# } +# +# # Make sure the plan and question are associated with the same template! +# validates :plan, :question, answer_for_correct_template: true end diff --git a/app/models/guidance_group.rb b/app/models/guidance_group.rb index afcb456..71535c3 100644 --- a/app/models/guidance_group.rb +++ b/app/models/guidance_group.rb @@ -32,13 +32,13 @@ # organisation followed by the name of the guidance group. # # @return [String] the display name for the guidance group - def display_name - if org.guidance_groups.count > 1 - return "#{org.name}: #{name}" - else - return org.name - end - end + def display_name + if org.guidance_groups.count > 1 + return "#{org.name}: #{name}" + else + return org.name + end + end ## # Returns the list of all guidance groups not coming from the given organisations diff --git a/app/models/plan.rb b/app/models/plan.rb index 00d52fb..0a7de28 100644 --- a/app/models/plan.rb +++ b/app/models/plan.rb @@ -5,8 +5,14 @@ has_many :phases, through: :template has_many :sections, through: :phases has_many :questions, through: :sections - has_many :answers + has_many :answers, dependent: :destroy has_many :notes, through: :answers + has_many :roles, dependent: :destroy + has_many :users, through: :roles + has_many :plan_guidance_groups, dependent: :destroy + has_many :guidance_groups, through: :plan_guidance_groups + + accepts_nested_attributes_for :template has_many :exported_plans has_many :roles @@ -27,6 +33,8 @@ # public is a Ruby keyword so using publicly enum visibility: [:organisationally_visible, :publicly_visible, :is_test, :privately_visible] + #TODO: work out why this messes up plan creation : + # briley: Removed reliance on :users, its really on :roles (shouldn't have a plan without at least a creator right?) It should be ok like this though now validates :template, :title, presence: true ## @@ -45,21 +53,6 @@ alias_method :super_settings, :settings - - - # EVALUATE CLASS AND INSTANCE METHODS BELOW - # - # What do they do? do they do it efficiently, and do we need them? - # Special note, these are both the methods in the old plan, and in the old project - - - - - - - - - ## # Proxy through to the template settings (or defaults if this plan doesn't have # an associated template) if there are no settings stored for this plan. @@ -78,34 +71,12 @@ # returns the template for this plan, or generates an empty template and returns that # # @return [Dmptemplate] the template associated with this plan - def dmptemplate -# self.project.try(:dmptemplate) || Dmptemplate.new - self.try(:template) || Template.new - end + def dmptemplate + #self.project.try(:dmptemplate) || Dmptemplate.new + self.template + end - ## - # returns the title for this project as defined by the settings - # - # @return [String] the title for this project - def title - if self.settings(:export).nil? - return I18n.t('tool_title2') - - else -# logger.debug "Title in settings: #{self.settings(:export).title}" - if self.settings(:export).title == "" -# if !self.version.nil? && !self.version.phase.nil? && !self.version.phase.title? then - if !self.template.nil? && !self.template.phases.empty? -# return self.version.phase.title - return self.template.phases.first.title - else - return I18n.t('tool_title2') - end - else - return self.settings(:export).title - end - end - end + ## # returns the most recent answer to the given question id @@ -114,76 +85,97 @@ # @param qid [Integer] the id for the question to find the answer for # @param create_if_missing [Boolean] if true, will genereate a default answer to the question # @return [Answer,nil] the most recent answer to the question, or a new question with default value, or nil - def answer(qid, create_if_missing = true) - answer = answers.where(:question_id => qid).order("created_at DESC").first - question = Question.find(qid) - if answer.nil? && create_if_missing then - answer = Answer.new - answer.plan_id = id - answer.question_id = qid - answer.text = question.default_value - default_options = Array.new - question.options.each do |option| - if option.is_default - default_options << option - end - end - answer.options = default_options - end - return answer - end + def answer(qid, create_if_missing = true) + answer = answers.where(:question_id => qid).order("created_at DESC").first + question = Question.find(qid) + if answer.nil? && create_if_missing then + answer = Answer.new + answer.plan_id = id + answer.question_id = qid + answer.text = question.default_value + default_options = Array.new + question.question_options.each do |option| + if option.is_default + default_options << option + end + end + answer.question_options = default_options + end + return answer + end ## # returns all of the sections for this version of the plan, and for the project's organisation # # @return [Array
,nil] either a list of sections, or nil if none were found - def sections - unless project.organisation.nil? then - sections = version.global_sections + project.organisation.all_sections(version_id) - else - sections = version.global_sections - end - return sections.uniq.sort_by &:number - end - ## - # returns the guidances associated with the project's organisation, for a specified question - # - # @param question [Question] the question to find guidance for - # @return [Array] the list of guidances which pretain to the specified question - def guidance_for_question(question) - guidances = {} - # If project org isn't nil, get guidance by theme from any "non-subset" groups belonging to project org - unless project.organisation.nil? then - project.organisation.guidance_groups.each do |group| - if !group.optional_subset && (group.dmptemplates.pluck(:id).include?(project.dmptemplate_id) || group.dmptemplates.count == 0) then - group.guidances.each do |guidance| - guidance.themes.where("id IN (?)", question.theme_ids).each do |theme| - guidances = self.add_guidance_to_array(guidances, group, theme, guidance) + def set_possible_guidance_groups + # find all the themes in this plan + # and get the guidance groups they belong to + logger.debug "RAY: set_possible_guidance_groups" + ggroups = [] + self.template.phases.each do |phase| + phase.sections.each do |section| + section.questions.each do |question| + question.themes.each do |theme| + theme.guidances.each do |guidance| + ggroups << guidance.guidance_group end end end end end - # Get guidance by theme from any guidance groups selected on creation - project.guidance_groups.each do |group| - if group.dmptemplates.pluck(:id).include?(project.dmptemplate_id) || group.dmptemplates.count == 0 then + + self.guidance_groups = ggroups.uniq + end + + + + + ## + # returns the guidances associated with the project's organisation, for a specified question + # + # @param question [Question] the question to find guidance for + # @return array of hashes with orgname, themes and the guidance itself + def guidance_for_question(question) + guidances = [] + logger.debug "RAY: guidance_for_question" + + # add in the guidance for the template org + unless self.template.org.nil? then + self.template.org.guidance_groups.each do |group| group.guidances.each do |guidance| - guidance.themes.where("id IN (?)", question.theme_ids).each do |theme| - guidances = self.add_guidance_to_array(guidances, group, theme, guidance) + common_themes = guidance.themes.all & question.themes.all + if common_themes.length > 0 + guidances << { orgname: self.template.org.name, theme: common_themes.join(','), guidance: guidance } end end end end - # Get guidance by question where guidance group was selected on creation or if group is organisation default - question.guidances.each do |guidance| - guidance.guidance_groups.each do |group| - if (group.organisation == project.organisation && !group.optional_subset) || project.guidance_groups.include?(group) then - guidances = self.add_guidance_to_array(guidances, group, nil, guidance) + + # add in the guidance for the user's org + unless self.owner.org.nil? then + self.owner.org.guidance_groups.each do |group| + group.guidances.each do |guidance| + common_themes = guidance.themes.all & question.themes.all + if common_themes.length > 0 + guidances << { orgname: self.template.org.name, theme: common_themes.join(','), guidance: guidance } + end end end end - + + # Get guidance by theme from any guidance groups currently selected + self.plan_guidance_groups.where(selected: true).each do |pgg| + group = pgg.guidance_group + group.guidances.each do |guidance| + common_themes = guidance.themes.all & question.themes.all + if common_themes.length > 0 + guidances << { orgname: self.template.org.name, theme: common_themes.join(','), guidance: guidance } + end + end + end + return guidances end @@ -219,37 +211,35 @@ ## # determines if the plan is editable by the specified user - # NOTE: This should be renamed to editable_by? # # @param user_id [Integer] the id for a user # @return [Boolean] true if user can edit the plan - def editable_by(user_id) - return project.editable_by(user_id) - end + def editable_by?(user_id) + role = roles.where(user_id: user_id).first + return role.present? && role.editor? + end ## # determines if the plan is readable by the specified user - # NOTE: This shoudl be renamed to readable_by? + # TODO: introduce explicit readable rather than implicit + # currently role with no flags = readable # # @param user_id [Integer] the id for a user # @return [Boolean] true if the user can read the plan - def readable_by(user_id) - if project.nil? - return false - else - return project.readable_by(user_id) - end - end + def readable_by?(user_id) + role = roles.where(user_id: user_id).first + return role.present? + end ## # determines if the plan is administerable by the specified user - # NOTE: This should be renamed to administerable_by? # # @param user_id [Integer] the id for the user # @return [Boolean] true if the user can administer the plan - def administerable_by(user_id) - return project.readable_by(user_id) - end + def administerable_by?(user_id) + role = roles.where(user_id: user_id).first + return role.present? && role.administrator? + end ## @@ -259,41 +249,41 @@ # for each question, it contains the answer_id, answer_created_by, answer_text, answer_options_id, aand answered_by # # @return [Status] - def status - status = { - "num_questions" => 0, - "num_answers" => 0, - "sections" => {}, - "questions" => {}, - "space_used" => 0 # percentage of available space in pdf used - } + def status + status = { + "num_questions" => 0, + "num_answers" => 0, + "sections" => {}, + "questions" => {}, + "space_used" => 0 # percentage of available space in pdf used + } - space_used = height_of_text(self.project.title, 2, 2) + space_used = height_of_text(self.title, 2, 2) - sections.each do |s| - space_used += height_of_text(s.title, 1, 1) - section_questions = 0 - section_answers = 0 - status["sections"][s.id] = {} - status["sections"][s.id]["questions"] = Array.new - s.questions.each do |q| - status["num_questions"] += 1 - section_questions += 1 - status["sections"][s.id]["questions"] << q.id - status["questions"][q.id] = {} - answer = answer(q.id, false) + sections.each do |s| + space_used += height_of_text(s.title, 1, 1) + section_questions = 0 + section_answers = 0 + status["sections"][s.id] = {} + status["sections"][s.id]["questions"] = Array.new + s.questions.each do |q| + status["num_questions"] += 1 + section_questions += 1 + status["sections"][s.id]["questions"] << q.id + status["questions"][q.id] = {} + answer = answer(q.id, false) - space_used += height_of_text(q.text) unless q.text == s.title - space_used += height_of_text(answer.try(:text) || I18n.t('helpers.plan.export.pdf.question_not_answered')) + space_used += height_of_text(q.text) unless q.text == s.title + space_used += height_of_text(answer.try(:text) || I18n.t('helpers.plan.export.pdf.question_not_answered')) - if ! answer.nil? then - status["questions"][q.id] = { - "answer_id" => answer.id, - "answer_created_at" => answer.created_at.to_i, - "answer_text" => answer.text, - "answer_option_ids" => answer.option_ids, - "answered_by" => answer.user.name - } + if ! answer.nil? then + status["questions"][q.id] = { + "answer_id" => answer.id, + "answer_created_at" => answer.created_at.to_i, + "answer_text" => answer.text, + "answer_option_ids" => answer.question_options.pluck(:id), + "answered_by" => answer.user.name + } q_format = q.question_format status["num_answers"] += 1 if (q_format.title == I18n.t("helpers.checkbox") || q_format.title == I18n.t("helpers.multi_select_box") || q_format.title == I18n.t("helpers.radio_buttons") || q_format.title == I18n.t("helpers.dropdown")) || answer.text.present? @@ -499,7 +489,19 @@ return section_questions end -private + + + ## + # assigns the passed user_id to the creater_role for the project + # gives the user rights to read, edit, administrate, and defines them as creator + # + # @param user_id [Integer] the user to be given priveleges' id + def assign_creator(user_id) + add_user(user_id, true, true, true) + end + + + ## # Based on the height of the text gathered so far and the available vertical @@ -556,11 +558,6 @@ - # BEGIN METHODS FROM PROJECT - # - - - ## # sets a new funder for the project # defaults to the first dmptemplate if the current template is nill and the funder has more than one dmptemplate @@ -577,19 +574,14 @@ end ## - # returns the funder id for the project + # returns the funder id for the plan # # @return [Integer, nil] the id for the funder def funder_id - if self.dmptemplate.nil? then + if self.template.nil? then return nil end - template_org = self.dmptemplate.organisation - if template_org.organisation_type.name == constant("organisation_types.funder").downcase - return template_org.id - else - return nil - end + return self.template.org end ## @@ -653,11 +645,12 @@ # # @return [Integer, nil] the organisation_id or nil def institution_id - if organisation.nil? - return nil - else - return organisation.root.id - end +# if organisation.nil? +# return nil +# else +# return organisation.root.id +# end + return template.org.id end ## @@ -685,14 +678,6 @@ end end - ## - # assigns the passed user_id to the creater_role for the project - # gives the user rights to read, edit, administrate, and defines them as creator - # - # @param user_id [Integer] the user to be given priveleges' id - def assign_creator(user_id) - add_user(user_id, true, true, true) - end ## # assigns the passed user_id as an editor for the project @@ -722,49 +707,6 @@ end ## - # whether or not the current plan is administrable by the user - # - # @param user_id [Integer] the user to check if has privleges - # @return [Boolean] true if user can administer project, false otherwise - def administerable_by(user_id) - user = project_groups.find_by_user_id(user_id) - if (! user.nil?) && user.project_administrator then - return true - else - return false - end - end - - ## - # whether or not the current plan is editable by the user - # - # @param user_id [Integer] the user to check if has privleges - # @return [Boolean] true if user can edit project, false otherwise - def editable_by(user_id) - user = project_groups.find_by_user_id(user_id) - if (! user.nil?) && user.project_editor then - return true - else - return false - end - end - - ## - # whether or not the current plan is readable by the user - # should be renamed to readable_by? - # - # @param user_id [Integer] the user to check if has privleges - # @return [Boolean] true if user can read project, false otherwise - def readable_by(user_id) - user = project_groups.find_by_user_id(user_id) - if (! user.nil?) then - return true - else - return false - end - end - - ## # returns the projects which the user can atleast read # # @param user_id [Integer] the user to lookup projects for @@ -826,7 +768,12 @@ # # @return [User] the creater of the project def owner - self.project_groups.find_by_project_creator(true).try(:user) + self.roles.each do |role| + if role.creator? + return role.user + end + end + return nil end ## @@ -866,13 +813,23 @@ # @param is_administrator [Boolean] whether or not the user can administrate the project # @param is_creator [Boolean] wheter or not the user created the project # @return [Array] + # + # TODO: change this to specifying uniqueness of user/plan association and handle + # that way + # def add_user(user_id, is_editor = false, is_administrator = false, is_creator = false) - group = ProjectGroup.new - group.user_id = user_id - group.project_creator = is_creator - group.project_editor = is_editor - group.project_administrator = is_administrator - project_groups << group + Role.where(plan_id: self.id, user_id: user_id).each do |r| + r.destroy + end + + role = Role.new + role.user_id = user_id + role.plan_id = id + + role.creator= is_creator + role.editor= is_editor + role.administrator= is_administrator + role.save end ## @@ -891,4 +848,59 @@ end end + + + ## + # Based on the height of the text gathered so far and the available vertical + # space of the pdf, estimate a percentage of how much space has been used. + # This is highly dependent on the layout in the pdf. A more accurate approach + # would be to render the pdf and check how much space had been used, but that + # could be very slow. + # NOTE: This is only an estimate, rounded up to the nearest 5%; it is intended + # for guidance when editing plan data, not to be 100% accurate. + # + # @param used_height [Integer] an estimate of the height used so far + # @return [Integer] the estimate of space used of an A4 portrain + def estimate_space_used(used_height) + @formatting ||= self.settings(:export).formatting + + return 0 unless @formatting[:font_size] > 0 + + margin_height = @formatting[:margin][:top].to_i + @formatting[:margin][:bottom].to_i + page_height = A4_PAGE_HEIGHT - margin_height # 297mm for A4 portrait + available_height = page_height * self.dmptemplate.settings(:export).max_pages + + percentage = (used_height / available_height) * 100 + (percentage / ROUNDING).ceil * ROUNDING # round up to nearest five + end + + ## + # Take a guess at the vertical height (in mm) of the given text based on the + # font-size and left/right margins stored in the plan's settings. + # This assumes a fixed-width for each glyph, which is obviously + # incorrect for the font-face choices available; the idea is that + # they'll hopefully average out to that in the long-run. + # Allows for hinting different font sizes (offset from base via font_size_inc) + # and vertical margins (i.e. for heading text) + # + # @param text [String] the text to estimate size of + # @param font_size_inc [Integer] the size of the font of the text, defaults to 0 + # @param vertical_margin [Integer] the top margin above the text, defaults to 0 + def height_of_text(text, font_size_inc = 0, vertical_margin = 0) + @formatting ||= self.settings(:export).formatting + @margin_width ||= @formatting[:margin][:left].to_i + @formatting[:margin][:right].to_i + @base_font_size ||= @formatting[:font_size] + + return 0 unless @base_font_size > 0 + + font_height = FONT_HEIGHT_CONVERSION_FACTOR * (@base_font_size + font_size_inc) + font_width = font_height * FONT_WIDTH_HEIGHT_RATIO # Assume glyph width averages at 2/5s the height + leading = font_height / 2 + + chars_in_line = (A4_PAGE_WIDTH - @margin_width) / font_width # 210mm for A4 portrait + num_lines = (text.length / chars_in_line).ceil + + (num_lines * font_height) + vertical_margin + leading + end + end diff --git a/app/models/plan_guidance_group.rb b/app/models/plan_guidance_group.rb new file mode 100644 index 0000000..7b76499 --- /dev/null +++ b/app/models/plan_guidance_group.rb @@ -0,0 +1,11 @@ +# Used to link plans to guidance groups +# the links are created at plan creation stage +# and link to all possible GGs +# then the selected field keeps track of which ones the user has turned on /off +# +class PlanGuidanceGroup < ActiveRecord::Base + belongs_to :plan + belongs_to :guidance_group + + attr_accessible :selected +end diff --git a/app/models/user.rb b/app/models/user.rb index b0ac4e9..52672c4 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -33,23 +33,6 @@ end end -=begin - has_many :projects, through: :roles do - def filter(query) - return self unless query.present? - t = self.arel_table - q = "%#{query}%" - conditions = t[:title].matches(q) - columns = %i( - grant_number identifier description principal_investigator data_contact - ) - columns = ['grant_number', 'identifier', 'description', 'principal_investigator', 'data_contact'] - columns.each {|col| conditions = conditions.or(t[col].matches(q)) } - self.where(conditions) - end - end -=end - has_many :user_identifiers has_many :identifier_schemes, through: :user_identifiers @@ -90,7 +73,7 @@ # @param user_email [Boolean] defaults to true, allows the use of email if there is no firstname or surname # @return [String] the email or the firstname and surname of the user def name(use_email = true) - if ((firstname.nil? && surname.nil?) || (firstname.strip == "" && surname.strip == "")) && use_email then + if (firstname.blank? && surname.blank?) || use_email then return email else name = "#{firstname} #{surname}" diff --git a/app/policies/note_policy.rb b/app/policies/note_policy.rb index 49b9766..8ffe95a 100644 --- a/app/policies/note_policy.rb +++ b/app/policies/note_policy.rb @@ -2,22 +2,22 @@ attr_reader :user attr_reader :note - def initialize(user, comment) + def initialize(user, note) raise Pundit::NotAuthorizedError, "must be logged in" unless user @user = user @note = note end def create? - Plan.find(@note.plan_id).readable_by(@user.id) + @note.answer.plan.readable_by?(@user.id) end def update? - Plan.find(@note.plan_id).readable_by(@user.id) + Plan.find(@note.plan_id).readable_by?(@user.id) end def archive? - Plan.find(@note.plan_id).readable_by(@user.id) + Plan.find(@note.plan_id).readable_by?(@user.id) end -end \ No newline at end of file +end diff --git a/app/policies/plan_policy.rb b/app/policies/plan_policy.rb index 585e2ac..3f5ba9a 100644 --- a/app/policies/plan_policy.rb +++ b/app/policies/plan_policy.rb @@ -7,49 +7,57 @@ @user = user @plan = plan end + + def show? + @plan.readable_by?(@user.id) + end def edit? - @plan.editable_by(@user.id) + @plan.editable_by?(@user.id) + end + + def update_guidance_choices? + @plan.editable_by?(@user.id) end def export? - @plan.readable_by(@user.id) + @plan.readable_by?(@user.id) end def update? - @plan.editable_by(@user.id) + @plan.editable_by?(@user.id) end def status? - @plan.readable_by(@user.id) + @plan.readable_by?(@user.id) end def section_answers? - @plan.readable_by(@user.id) + @plan.readable_by?(@user.id) end def locked? - @plan.readable_by(@user.id) + @plan.readable_by?(@user.id) end def delete_recent_locks? - @plan.editable_by(@user.id) + @plan.editable_by?(@user.id) end def unlock_all_sections? - @plan.editable_by(@user.id) + @plan.editable_by?(@user.id) end def lock_section? - @plan.editable_by(@user.id) + @plan.editable_by?(@user.id) end def unlock_section? - @plan.editable_by(@user.id) + @plan.editable_by?(@user.id) end def answer? - @plan.readable_by(@user.id) + @plan.readable_by?(@user.id) end -end \ No newline at end of file +end diff --git a/app/views/layouts/_navigation.html.erb b/app/views/layouts/_navigation.html.erb index 8fa890a..dca92ca 100644 --- a/app/views/layouts/_navigation.html.erb +++ b/app/views/layouts/_navigation.html.erb @@ -46,21 +46,21 @@ <% end %> <% else %> <% if user_signed_in? %> - - <% if (namespace == "projects" || namespace == "plans") && current_path != "/projects/new" then %> + + <% if namespace == "plans" && current_path != "/plans/new" then %>
  • <% else %>
  • <% end %> - <%= link_to t("helpers.view_plans_label"), projects_path %> + <%= link_to t("helpers.view_plans_label"), plans_path %>
  • - <% if current_path == "/projects/new" then %> + <% if current_path == "/plans/new" then %>
  • <% else %>
  • <% end %> - <%= link_to t("helpers.create_plan_label"), new_project_path %> + <%= link_to t("helpers.create_plan_label"), new_plan_path %>
  • <% else %> diff --git a/app/views/phases/_add_note.html.erb b/app/views/phases/_add_note.html.erb new file mode 100644 index 0000000..00584fd --- /dev/null +++ b/app/views/phases/_add_note.html.erb @@ -0,0 +1,20 @@ + + +<% new_note = Note.new %> +<% answerid = answer.id %> + +<%= form_for :new_note, + :url => {:controller => :notes, :action => :create }, + :html=>{:method=>:post, :id => "new_note_form_#{answerid}", :class => "add_note_form"} do |f| %> + <%= f.hidden_field :user_id, :value => current_user.id %> + <%= f.hidden_field :answer_id, :value => answerid %> + + <%= text_area_tag("#{answerid}new_note_text".to_sym, "" , class: "tinymce") %> +
    + + +
    + <%= f.submit t("helpers.submit.save"), :class => "btn btn-primary new_comment_submit_button" %> +
    +
    +<%end%> diff --git a/app/views/phases/_answer_form.html.erb b/app/views/phases/_answer_form.html.erb new file mode 100644 index 0000000..289ef9b --- /dev/null +++ b/app/views/phases/_answer_form.html.erb @@ -0,0 +1,209 @@ + + +
    + + <% q_format = question.question_format %> + +
    + <%= semantic_form_for answer, :url => {:controller => :answers, :action => :update }, :html=>{:method=>:put}, :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.where(org_id: plan.template.org_id).first %> + <% if suggested_answer && suggested_answer.text.present? %> +
    + + <% if suggested_answer.is_example? then %> + <%= t("org_admin.questions.example_answer_label")%> + <%else%> + <%= t("org_admin.questions.suggested_answer_label")%> + <%end%> + + +
    +

    + <%= raw suggested_answer.text %> +

    +
    +
    + <% end %> + + + <% if [ @checkbox, @multi, @radio, @dropdown ].include?( q_format.id ) %> + <% options = question.options.order("number") %> + + + <% if q_format.id == @checkbox %> + <%= f.input :options, :as => :check_boxes, :collection => options, :label => false, :input_html => { :id => "options-#{question.id}" } %> + <% elsif q_format.id == @multi %> + <%= f.input :options, :as => :select, :collection => options, :label => false, :input_html => { :multiple => true , :id => "options-#{question.id}" } %> + <% elsif q_format.id == @radio %> +
      + <% options.each do |op| %> +
    1. + <% if answer.option_ids[0] == op.id then%> + <%= f.radio_button :option_ids, op.id, :checked => true, id: "answer_option_ids_#{op.id}"%> + <%else%> + <%= f.radio_button :option_ids, op.id, :checked => false, id: "answer_option_ids_#{op.id}"%> + <% end %> + <%= raw op.text %>
    2. + <% end %> +
    + <% elsif q_format.id == @dropdown %> + <%= f.input :options, :as => :select, :collection => options, :label => false, :input_html => { :multiple => false, :id => "options-#{question.id}" } %> + <% end %> + + + + <% if question.option_comment_display == true %> + <%= label_tag("answer-text-#{question.id}".to_sym, t("helpers.comment")) %> + <%= text_area_tag("answer-text-#{question.id}".to_sym, answer.text, class: "tinymce") %> + <%end%> + <% end %> + + <% if q_format.id == @textfield %> + <%= text_field_tag("answer-text-#{question.id}".to_sym, strip_tags(answer.text), class: "question_text_field") %> + <% elsif q_format.id == @textarea %> + <%= text_area_tag("answer-text-#{question.id}".to_sym, answer.text, class: "tinymce") %> + <% end %> + + <% end %> + + + <%= f.actions do %> + <%= f.action :submit, :label => t("helpers.save"), :button_html => { :class => "btn btn-primary"} %> + + <% end %> + <% end %> +
    + + <% if answer.created_at.nil? %> + <%= t("helpers.notanswered") %> + <% else %> + <%= t("helpers.answered_by")%><%= answer.created_at %><%= t("helpers.answered_by_part2")%><%= answer.user.name %> + <% end %> +
    + + + + +
    + +
    + <% comments = answer.notes.all %> + <%= hidden_field_tag :question_id, question.id, :class => "question_id" %> +
      + <% if (!question.guidance.nil? && question.guidance != "") || question_guidances.count > 0 then %> + + <% css_style_comment_div = "display: none;"%> + <% css_style_guidance_div = ""%> +
    • + <%= link_to t("helpers.guidance_accordion_label"), "#", :class => "guidance_accordion_button" %> +
    • +
    • + <% if comments.count > 0 then%> + <% comments_label_with_count = "#{t("helpers.comment_accordion_label")} (#{comments.count})"%> + <%= link_to comments_label_with_count , "#", :class => "comments_accordion_button" %> + <%else%> + <%= link_to t("helpers.add_comment_accordion_label"), "#", :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 = "#{t("helpers.comment_accordion_label")} (#{comments.count})"%> +

      <%= comments_label_with_count %>

      + <%else%> +

      <%= t("helpers.add_comment_accordion_label") %>

      + <%end%> +
    • + <%end%> +
    +
    + + + +
    +
    + + + <% if question.guidance.present? %> +
    + + + + + +
    +
    <%= raw question.guidance %>
    +
    + +
    + <% end %> + + + + + <% question_guidances.each_index do |gindex| %> + <% qguidance = @question_guidances[gindex] + orgname = qguidance[:orgname] + theme = qguidance[:theme] + guidance = qguidance[:guidance] + %> + +
    + + + + + +
    +
    <%= raw guidance.text %>
    +
    + +
    + <% end %> + +
    +
    + + +
    + <%= render :partial => "note", locals: {answer: answer, plan: plan}%> +
    + +
    + + +<% if last_question_id == question.id then %> +
    +<% else %> +
    +<% end %> diff --git a/app/views/phases/_answer_form_ro.html.erb b/app/views/phases/_answer_form_ro.html.erb new file mode 100644 index 0000000..64a0fb0 --- /dev/null +++ b/app/views/phases/_answer_form_ro.html.erb @@ -0,0 +1,248 @@ + +<% 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.where(org_id: @plan.template.org_id).first %> + <% if suggested_answer.present? %> +
    + + <% if suggested_answer.is_example? then %> + <%= t("org_admin.questions.example_answer_label")%> + <%else%> + <%= t("org_admin.questions.suggested_answer_label")%> + <%end%> + +
    +

    + <%= raw suggested_answer.text %> +

    +
    +
    + <% end %> + + + <% if q_format.title == t("helpers.checkbox") || q_format.title == t("helpers.multi_select_box") || q_format.title == t("helpers.radio_buttons") || q_format.title == t("helpers.dropdown") then%> + <% options = question.options.order("number") %> + + <% if q_format.title == t("helpers.checkbox") 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 == t("helpers.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 == t("helpers.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 == t("helpers.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, t("helpers.comment")) %> + <%= text_area_tag("answer-text-#{question.id}".to_sym, answer.text, class: "tinymce") %> + <%end%> + + + <% elsif q_format.title == t("helpers.text_field") then %> + <%= text_field_tag("answer-text-#{question.id}".to_sym, strip_tags(answer.text), class: "question_text_field") %> + + <% elsif q_format.title == t("helpers.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 => t("helpers.save"), :button_html => { :class => "btn btn-primary"}, :input_html => { :disabled => true } %> + <% else %> + <%= f.action :submit, :label => t("helpers.save"), :button_html => { :class => "btn btn-primary"} %> + <% end %> + + <% end %> + <% end %> +
    + <% end %> + +
    > +

    <%= question.text %>

    +
    + <% if q_format.title == t("helpers.checkbox") || q_format.title == t("helpers.multi_select_box") || q_format.title == t("helpers.radio_buttons") || q_format.title == t("helpers.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 %> + <%= t("helpers.notanswered") %> + <% else %> + <%= t("helpers.answered_by")%><%= answer.created_at %><%= t("helpers.answered_by_part2")%><%= answer.user.name %> + <% end %> + +
    + + + +
    +
    + <% @comments = Notes.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 t("helpers.guidance_accordion_label"), "#", :class => "guidance_accordion_button" %> +
    • +
    • + <% if @comments.count > 0 then%> + <% comments_label_with_count = "#{t("helpers.comment_accordion_label")} (#{@comments.count})"%> + <%= link_to comments_label_with_count , "#", :class => "comments_accordion_button" %> + <%else%> + <%= link_to t("helpers.add_comment_accordion_label"), "#", :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 = "#{t("helpers.comment_accordion_label")} (#{@comments.count})"%> +

      <%= comments_label_with_count %>

      + <%else%> +

      <%= t("helpers.add_comment_accordion_label") %>

      + <%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/phases/_archive_note.html.erb b/app/views/phases/_archive_note.html.erb new file mode 100644 index 0000000..904c82d --- /dev/null +++ b/app/views/phases/_archive_note.html.erb @@ -0,0 +1,23 @@ + +<%= form_for(note, :url => {:controller => :notes, :action => :archive } , :html => { :method => :put, :class => "archive_note_form", :id => "archive_note_form_#{note.id}"}) do |f| %> + <%= f.hidden_field :id, :value => note.id %> + <%= f.hidden_field :archived_by, :value => current_user.id %> + + <%= render :partial => "view_note", locals: {note: note} %> + + <% if current_user.id == note.user_id then %> + <%= t('helpers.notes.archive_own_note_question')%> + <% button_label = t("helpers.notes.archive_own_comment_button_label") %> + <% else%> + <%= t("helpers.notes.archive_note_question")%> + <% button_label = t("helpers.notes.archive_comment_button_label") %> + <%end%> + + +
    + <%= hidden_field_tag :note_id, note.id, :class => "comment_id" %> + <%= f.submit button_label, :class => "btn btn-primary archive_comment_submit_button" %> + <%= link_to t("helpers.submit.cancel"), "#", :class => "cancel_archive_comment btn cancel" %> +
    +
    +<%end%> diff --git a/app/views/phases/_edit_note.html.erb b/app/views/phases/_edit_note.html.erb new file mode 100644 index 0000000..f931d7f --- /dev/null +++ b/app/views/phases/_edit_note.html.erb @@ -0,0 +1,16 @@ + + +<%= form_for(note, :url => {:controller => :notes, :action => :update } , :html => { :method => :put, :class => "edit_note_form", :id=> "edit_note_form_#{note.id}"}) do |f| %> + <%= f.hidden_field :id, :value => note.id %> + + <%= text_area_tag("#{note.id}_note_text".to_sym, note.text , class: "tinymce") %> +
    + + +
    + <%= hidden_field_tag :answer, note.answer_id, :class => "answer_id" %> + <%= hidden_field_tag :note_id, note.id, :class => "note_id" %> + <%= f.submit t("helpers.submit.save"), :class => "btn btn-primary edit_note_submit_button" %> +
    +
    +<%end%> diff --git a/app/views/phases/_list_notes.html.erb b/app/views/phases/_list_notes.html.erb new file mode 100644 index 0000000..12b17ab --- /dev/null +++ b/app/views/phases/_list_notes.html.erb @@ -0,0 +1,87 @@ + + +<% if notes.count > 1 then%> + <% style_to_add = "height:150px; overflow-y:auto;" %> +<%else%> + <% style_to_add = "" %> +<%end%> + +
    + +
    + + + <% notes.order("updated_at DESC").each do |c|%> + + + + + <%end%> + +
    + <% user = c.user %> + <%= user.name %>
    + (<%= l c.updated_at, format: :custom %>) +
    + + <% if c.archived %> + + <% if c.archived_by == current_user.id %> + <%= t("helpers.comments.retracted")%> + <% else %> + <% archived_by_user = User.find(c.archived_by) %> + <%= t("helpers.comments.clear_by")%> <%= archived_by_user.name %> + <%end%> + + <%else%> + + <%= link_to t("helpers.comments.view_label"),"#", :class => "dmp_table_link view_comment_button" %> + <%= hidden_field_tag :note_id, c.id, :class => "comment_id" %> + + <% if current_user.id == c.user_id %> + <%= link_to t("helpers.comments.edit_label"),"#", :class => "dmp_table_link edit_comment_button" %> + <%= hidden_field_tag :note_id, c.id, :class => "comment_id" %> + <%= link_to t("helpers.comments.retract_label"),"#", :class => "dmp_table_link archive_comment_button" %> + <% end%> + + <% if @plan.administerable_by?(current_user.id) && current_user.id != c.user_id %> + <%= hidden_field_tag :note_id, c.id, :class => "comment_id" %> + <%= link_to t("helpers.comments.clear_label"),"#", :class => "dmp_table_link archive_comment_button" %> + <% end%> + <%end%> + +
    +
    + +
    + + +<% notes_not_archived = notes.where("archived IS NULL") %> +<% latest_note = notes_not_archived.order("updated_at DESC").first %> +<% if !latest_note.nil? then%> +
    + <%= render :partial => "view_note", locals: {note: latest_note} %> +
    +
    +<%end%> + +<%notes.order("updated_at DESC").each do |com|%> + + + + + + + + + +<%end%> diff --git a/app/views/phases/_note.html.erb b/app/views/phases/_note.html.erb new file mode 100644 index 0000000..9a9906a --- /dev/null +++ b/app/views/phases/_note.html.erb @@ -0,0 +1,37 @@ + + + <% notes = answer.notes.all %> + <% answerid = answer.id %> + <%= hidden_field_tag :answer_id, answer.id %> + + <% if notes.count > 0 %> + + +
    + <%= link_to t("helpers.comments.add_comment_label"),'#', :class => "btn btn-primary add_comment_button" %> +
    + +
    + + + <%= render :partial => "list_notes", locals: {notes: notes, plan:plan} %> + +
    + + +
    + <%= link_to t("helpers.comments.add_comment_label"),'#', :class => "btn btn-primary add_comment_button" %> +
    + +
    + + + + + <% else%> + <%= t("helpers.comments.add_comment_text")%> + <%= render :partial => "add_note", locals: {answer: answer}%> + <% end%> diff --git a/app/views/phases/_view_note.html.erb b/app/views/phases/_view_note.html.erb new file mode 100644 index 0000000..6b7737f --- /dev/null +++ b/app/views/phases/_view_note.html.erb @@ -0,0 +1,11 @@ + +<% user = User.find(note.user_id) %> +
    +
    +
    +
      +
    • <%= t("helpers.comments.commented_by")%>

    • +
    • <%= user.name%> (<%= l note.updated_at, format: :custom %>)
    • +
    • <%= raw note.text %>
    • +
    +
    diff --git a/app/views/phases/edit.html.erb b/app/views/phases/edit.html.erb new file mode 100644 index 0000000..51e638a --- /dev/null +++ b/app/views/phases/edit.html.erb @@ -0,0 +1,166 @@ +<%- model_class = Plan -%> +<% javascript "plans.js" %> + + + + + +<%= render :partial => "/plans/plan_title", locals: {plan: @plan} %> + + + +<% status = @plan.status %> +
    + <%space_used = status["space_used"].to_i + space_title = t("helpers.plan.export.space_used", space_used: space_used, num_pages: @plan.template.settings(:export).max_pages) + answered = %(#{status["num_answers"]}/#{status["num_questions"]})%> +
    + <%= answered -%> <%= t("helpers.project.questions_answered")%> + ;" title="<%= answered -%> <%= t("helpers.project.questions_answered")%>"> +
    + +
    + +
    + = 100 ? "class=bar-full-text" : "" -%>><%= space_title -%> + " style="width: <%= space_used -%>%;" title="<%= space_title -%>"> +
    +
    + + + +<%= render :partial => "/plans/plan_nav_tabs", locals: {plan: @plan, active: @phase.title } %> + + + +
    + +
    + <% @sections.each do |section| %> + + + <% if session[:question_id_comments].to_i != 0 then %> + <% question_from_comment = Question.find(session[:question_id_comments])%> + <% if section.id == question_from_comment.section_id then %> + <%= hidden_field_tag :comment_section_id, question_from_comment.section_id, :class => "comment_section_id" %> + <%end%> + <% end%> + + + +
    + + + <% num_section_questions = section.questions.count %> + <% num_section_answers = @section_answers[section.id] %> + <% question_word = "questions" %> + <% if num_section_questions == 1 then %> + <% question_word = "question" %> + <% end %> + <% section_status = "#{num_section_questions} #{question_word}, #{num_section_answers} answered" %> + + + + + +
    +
    + <%= raw section.description %> +
    + +
    + + +
    +

    <%= t ('helpers.loading')%>

    +
    + + + + +
    + <% section.questions.order("number").each do |question| %> + <% if question.id == session[:question_id_comments].to_i then id_css = "current_question" end %> +
    + <% partialname = "answer_form" + if @readonly + partialname += "_ro" + end + %> + + <% guidances = @plan.guidance_for_question(question) %> + + <%= render partial: partialname, + locals: { + plan: @plan, + answer: @plan.answer(question.id), + question_guidances: guidances, + question: question, + last_question_id: section.questions.order("number DESC").first.id + } + %> +
    + <% end %> +
    +
    +
    +
    + + + + + <% end %> +
    + + <%= tinymce :content_css => asset_path("application.css"), :setup => "function(editor){editor.on('change', function(e){$.fn.check_textarea(editor)});}" %> +
    + + +<%= render :partial => "plans/export", locals: {plan: @plan} %> + + +<% session.delete(:question_id_comments)%> diff --git a/app/views/plans/_add_note.html.erb b/app/views/plans/_add_note.html.erb deleted file mode 100644 index 957e0ef..0000000 --- a/app/views/plans/_add_note.html.erb +++ /dev/null @@ -1,20 +0,0 @@ - - -<% @new_note = Note.new %> - -<%= form_for :new_note, :url => {:controller => :notes, :action => :create } , :html=>{:method=>:post, :id => "new_note_form_#{questionId}", :class => "add_note_form"} do |f| %> - <%= f.hidden_field :user_id, :value => current_user.id %> - <%= f.hidden_field :question_id, :value => questionId %> - <%= f.hidden_field :plan_id, :value => planId %> - - <%= text_area_tag("#{questionId}new_note_text".to_sym, "" , class: "tinymce") %> -
    - <% question = Question.find(questionId)%> - -
    - <%= hidden_field_tag :section_id, question.section_id, :class => "section_id" %> - <%= hidden_field_tag :question_id, question.id, :class => "question_id" %> - <%= f.submit t("helpers.submit.save"), :class => "btn btn-primary new_comment_submit_button" %> -
    -
    -<%end%> \ No newline at end of file diff --git a/app/views/plans/_archive_note.html.erb b/app/views/plans/_archive_note.html.erb deleted file mode 100644 index a101e30..0000000 --- a/app/views/plans/_archive_note.html.erb +++ /dev/null @@ -1,28 +0,0 @@ - - -<%= form_for(note, :url => {:controller => :notes, :action => :archive } , :html => { :method => :put, :class => "archive_note_form", :id => "archive_note_form_#{note.id}"}) do |f| %> - <%= f.hidden_field :id, :value => note.id %> - <%= f.hidden_field :archived_by, :value => current_user.id %> - - <%= render :partial => "view_note", locals: {note: note} %> - - <% if current_user.id == note.user_id then %> - <%= t('helpers.notes.archive_own_note_question')%> - <% button_label = t("helpers.notes.archive_own_comment_button_label") %> - <% else%> - <%= t("helpers.notes.archive_note_question")%> - <% button_label = t("helpers.notes.archive_comment_button_label") %> - <%end%> - - -
    - <% question = Question.find(note.question_id)%> - <%= hidden_field_tag :plan_id, note.plan_id, :class => "plan_id" %> - <%= hidden_field_tag :note_id, note.id, :class => "comment_id" %> - <%= hidden_field_tag :section_id, question.section_id, :class => "section_id" %> - <%= f.submit button_label, :class => "btn btn-primary archive_comment_submit_button" %> - <%= hidden_field_tag :note_id, note.id, :class => "comment_id" %> - <%= link_to t("helpers.submit.cancel"), "#", :class => "cancel_archive_comment btn cancel" %> -
    -
    -<%end%> \ No newline at end of file diff --git a/app/views/plans/_dropdowns_new_plan.html.erb b/app/views/plans/_dropdowns_new_plan.html.erb new file mode 100644 index 0000000..5413579 --- /dev/null +++ b/app/views/plans/_dropdowns_new_plan.html.erb @@ -0,0 +1,41 @@ + + +<%= semantic_form_for @plan, :url => {:controller => :plans, :action => :create }, :html=>{:method=>:post} do |f| %> + <%= f.inputs do %> + <%= hidden_field_tag :default_tag, "false" ,:id => "default_tag" %> +
    + +

    <%= t('helpers.project.create_page.title') %>

    +
    +

    <%= raw t('helpers.project.create_page.desc_html')%>

    +
    + + + + <% end %> + + + <%= f.actions do %> + <%= f.action :submit, + :as => :button, + :input_html => { :id => "create-plan-button", :class => "btn btn-primary"}, + :label => t('helpers.project.create') %> + <% end %> + +<% end %> diff --git a/app/views/plans/_edit_note.html.erb b/app/views/plans/_edit_note.html.erb deleted file mode 100644 index 6294200..0000000 --- a/app/views/plans/_edit_note.html.erb +++ /dev/null @@ -1,18 +0,0 @@ - - -<%= form_for(note, :url => {:controller => :notes, :action => :update } , :html => { :method => :put, :class => "edit_note_form", :id=> "edit_note_form_#{note.id}"}) do |f| %> - <%= f.hidden_field :id, :value => note.id %> - - <%= text_area_tag("#{note.id}_note_text".to_sym, note.text , class: "tinymce") %> -
    - - -
    - <% question = Question.find(note.question_id)%> - <%= hidden_field_tag :plan_id, note.plan_id, :class => "plan_id" %> - <%= hidden_field_tag :note_id, note.id, :class => "note_id" %> - <%= hidden_field_tag :section_id, question.section_id, :class => "section_id" %> - <%= f.submit t("helpers.submit.save"), :class => "btn btn-primary edit_note_submit_button" %> -
    -
    -<%end%> \ No newline at end of file diff --git a/app/views/plans/_export.html.erb b/app/views/plans/_export.html.erb index 6c0e8de..d47ae8d 100644 --- a/app/views/plans/_export.html.erb +++ b/app/views/plans/_export.html.erb @@ -1,9 +1,9 @@ - diff --git a/app/views/plans/_list_notes.html.erb b/app/views/plans/_list_notes.html.erb deleted file mode 100644 index 10a16f0..0000000 --- a/app/views/plans/_list_notes.html.erb +++ /dev/null @@ -1,79 +0,0 @@ - -<% if notes.count > 1 then%> - <% style_to_add = "height:150px; overflow-y:auto;" %> -<%else%> - <% style_to_add = "" %> -<%end%> -
    -
    - - - <% notes.order("updated_at DESC").each do |c|%> - - - - - <%end%> - -
    - <% user = User.find(c.user_id) %> - <%= user.name %>
    - (<%= l c.updated_at, format: :custom %>) -
    - <% if c.archived == true then %> - <% if c.archived_by == current_user.id then%> - <%= t("helpers.comments.retracted")%> - <% else %> - <% archived_by_user = User.find(c.archived_by) %> - <%= t("helpers.comments.clear_by")%> <%= archived_by_user.name %> - <%end%> - <%else%> - <%= link_to t("helpers.comments.view_label"),"#", :class => "dmp_table_link view_comment_button" %> - <%= hidden_field_tag :note_id, c.id, :class => "comment_id" %> - <% if current_user.id == c.user_id then %> - <%= link_to t("helpers.comments.edit_label"),"#", :class => "dmp_table_link edit_comment_button" %> - - <%= hidden_field_tag :note_id, c.id, :class => "comment_id" %> - <%= link_to t("helpers.comments.retract_label"),"#", :class => "dmp_table_link archive_comment_button" %> - <% end%> - <% project_id = Plan.find(c.plan_id).project_id%> - <% if (Project.find(project_id).administerable_by(current_user.id) && current_user.id != c.user_id )then%> - <%= hidden_field_tag :note_id, c.id, :class => "comment_id" %> - <%= link_to t("helpers.comments.clear_label"),"#", :class => "dmp_table_link archive_comment_button" %> - <% end%> - <%end%> -
    -
    - -
    - - -<% notes_not_archived = notes.where("archived IS NULL") %> -<% latest_note = notes_not_archived.order("updated_at DESC").first %> -<% if !latest_note.nil? then%> -
    - <%= render :partial => "view_note", locals: {note: latest_note} %> -
    -
    -<%end%> - -<%notes.order("updated_at DESC").each do |com|%> - - - - - - - - - - <%end%> diff --git a/app/views/plans/_note.html.erb b/app/views/plans/_note.html.erb deleted file mode 100644 index a6ed343..0000000 --- a/app/views/plans/_note.html.erb +++ /dev/null @@ -1,35 +0,0 @@ - - - - -<% @notes = Note.where("question_id = ? AND plan_id = ?", questionId, plan_id) %> -<%= hidden_field_tag :question_id, questionId, :class => "question_id" %> - -<% if @notes.count > 0 then%> - -
    - <%= link_to t("helpers.comments.add_comment_label"),'#', :class => "btn btn-primary add_comment_button" %> - -
    -
    -
    - - <%= render :partial => "list_notes", locals: {notes: @notes}%> -
    -
    - -
    - <%= link_to t("helpers.comments.add_comment_label"),'#', :class => "btn btn-primary add_comment_button" %> -
    -
    -
    - - - -<% else%> - <%= t("helpers.comments.add_comment_text")%> - <%= render :partial => "add_note", locals: {questionId: questionId, planId: plan_id}%> -<% end%> diff --git a/app/views/plans/_plan_details.html.erb b/app/views/plans/_plan_details.html.erb new file mode 100644 index 0000000..430288b --- /dev/null +++ b/app/views/plans/_plan_details.html.erb @@ -0,0 +1,321 @@ + +
    + + + + +
    "> + +
    +

    + <%= raw t('helpers.project.project_details_editing_text_html')%> +

    +
    + + +
    + + <%= semantic_form_for @plan, :url => {:controller => :plans, :action => :update }, :html=>{:method=>:put} do |f| %> + <%= f.inputs do %> +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    <%= t('helpers.project.project_name') %> + <%= f.text_field :title, :class => 'text_field has-tooltip', 'data-toggle' => "tooltip", 'title' => t('helpers.project.project_name_help_text') %> +
    <%= t('helpers.project.project_identifier') %> + <%= f.text_field :identifier, :class => 'text_field has-tooltip', 'data-toggle' => "tooltip", 'title' => t('helpers.project.project_identifier_help_text') %> +
    <%= t('helpers.project.grant_title') %> + <%= f.text_field :grant_number, :class => 'text_field has-tooltip', 'data-toggle' => "tooltip", 'title' => t('helpers.project.grant_help_text') %> +
    <%= t('helpers.project.principal_investigator') %> + <%= f.text_field :principal_investigator, :class => 'text_field has-tooltip', 'data-toggle' => "tooltip", 'title' => t('helpers.project.principal_investigator_help_text') %> +
    <%= t('helpers.project.principal_investigator_id') %> + <%= f.text_field :principal_investigator_identifier, :class => 'text_field has-tooltip', 'data-toggle' => "tooltip", 'title' => t('helpers.project.principal_investigator_id_help_text') %> +
    <%= t('helpers.project.project_data_contact') %> + <%= f.text_field :data_contact, :class => 'text_field has-tooltip', 'data-toggle' => "tooltip", 'title' => t('helpers.project.project_data_contact_help_text') %> +
    <%= t('helpers.desc') %> + <%= f.text_area :description, { :rows => 7, :class => 'text_area has-tooltip', 'data-toggle' => "tooltip", 'data-html' => "true", 'title'=> t('helpers.project.project_desc_help_text_html')} %> +
    +
    + <% end %> + + <%= f.actions do %> +
    + <%= f.submit t("helpers.submit.save"), :class => 'btn btn-primary' %> + <%= t("helpers.links.cancel") %> +
    + <%end%> + <%end%> +
    + + + +
    "> +
    +

    <%= t('helpers.project.project_details_text_html')%>

    +
    + + + + + +
    + + + + + + + + + + + + + + + + + + + + <% if !@plan.principal_investigator_identifier.nil? && @plan.principal_investigator_identifier != "" then %> + + + + + <%end%> + + + + + + + + +
    <%= t('helpers.project.project_name') %><%= @plan.title %>
    <%= t('helpers.project.project_identifier') %> + <% if !@plan.identifier.nil? && @plan.identifier != "" then %> + <%= @plan.identifier %> + <%else%> + - + <%end%> +
    <%= t('helpers.project.grant_title') %> + <% if !@plan.grant_number.nil? && @plan.grant_number!= "" then %> + <%= @plan.grant_number %> + <%else%> + - + <%end%> +
    <%= t('helpers.project.principal_investigator') %><% if !@plan.principal_investigator.nil? && @plan.principal_investigator != "" then %> + <%= @plan.principal_investigator %> + <%else%> + - + <%end%> +
    <%= t('helpers.project.principal_investigator_id') %> + <%= @plan.principal_investigator_identifier %> +
    <%= t('helpers.project.project_data_contact') %><% if !@plan.data_contact.nil? && @plan.data_contact != "" then%> + <%= @plan.data_contact %> + <%else%> + - + <%end%> +
    <%= t('helpers.desc') %><% if !@plan.description.nil? && @plan.description != "" then%> + <%= @plan.description %> + <%else%> + - + <%end%> +
    +
    +
    + + + +
    +
    + +
    +
    + <%= semantic_form_for @plan, :url => {:controller => :plans, :action => :update_guidance_choices }, :html=>{:method=>:put}, :remote => true do |f| %> + <%= f.inputs do %> + <%= f.input :plan_guidance_groups, + :as => :check_boxes, + :collection => selected_guidance_groups %> + <% end %> + + <%= f.actions do %> +
    + <%= f.submit t("helpers.submit.save"), :class => 'btn btn-primary' %> + <%= t("helpers.links.cancel") %> +
    + <%end%> + <%end%> +
    +
    +
    +
    + +
    + +

    <%= t('helpers.project.project_static_info')%>

    + + + + <%if @plan.template.org.name? %> + + + + + <%end%> + <%if @plan.template.customization_of.present? %> + <%= " (Customised from #{ @plan.template.customization_of.org.name })" %> + <%end%> +
    <%= constant("organisation_types.funder") %><%= @plan.template.org.name %>
    + +
    + + + <% phases = @plan.template.phases %> + <% if phases.any? %> + <% if phases.count == 1 then %> + <% phases.each do |phase| %> + +
    + <%= link_to t('helpers.answer_questions'), edit_plan_path(@plan), :class => 'btn btn-primary' %> + <%= t('helpers.export') %> +
    + <%= render :partial => "plans/export", locals: {plan: plan} %> +
    +

    <%= raw phase.description %>

    + <% if !phase.sections.nil? %> + + + + + + + + + <% phase.sections.each do |section| %> + + + + + <%end%> + +
    <%= t('helpers.sections_label')%><%= t('helpers.questions_label')%>
    +

    <%= section.title %>

    +
    + <% if section.questions.any? %> + <% questions = section.questions.sort_by(&:number) %> +
      + <% questions.each do |ques|%> +
    • + <%= raw ques.text %> +
    • + <%end%> +
    + <%end%> +
    + <%end%> + <%end%> + <%else%> +
    + <%= raw @plan.template.description %> +
    + <% phases.each do |phase| %> +
    +
    + +
    +
    +
    + <%= link_to t('helpers.answer_questions'), edit_plan_path(@plan), :class => 'btn btn-primary' %> + <%= t('helpers.export') %> +
    + <%= render :partial => "plans/export", locals: {plan: @plan} %> +
    +

    <%= raw phase.description %> +

    + + <% if !phase.sections.nil? %> + + + + + + + + + <% phase.sections.each do |section| %> + + + + + <%end%> + +
    <%= t('helpers.sections_label')%><%= t('helpers.questions_label')%>
    +

    <%= section.title %>

    +
    + <% if section.questions.any? %> + <% questions = section.questions.sort_by(&:number) %> +
      + <% questions.each do |ques|%> +
    • + - <%= raw ques.text %> +
    • + <%end%> +
    + <%end%> +
    + <%end%> +
    +
    +
    +
    + <%end%> + <%end%> + <%end%> +
    diff --git a/app/views/plans/_plan_nav_tabs.html.erb b/app/views/plans/_plan_nav_tabs.html.erb new file mode 100644 index 0000000..3ae1018 --- /dev/null +++ b/app/views/plans/_plan_nav_tabs.html.erb @@ -0,0 +1,38 @@ + + diff --git a/app/views/plans/_plan_title.html.erb b/app/views/plans/_plan_title.html.erb new file mode 100644 index 0000000..d134aa1 --- /dev/null +++ b/app/views/plans/_plan_title.html.erb @@ -0,0 +1,8 @@ + +
    +
    +

    + <%= plan.title %> +

    +
    +
    diff --git a/app/views/plans/_view_note.html.erb b/app/views/plans/_view_note.html.erb deleted file mode 100644 index 6b7737f..0000000 --- a/app/views/plans/_view_note.html.erb +++ /dev/null @@ -1,11 +0,0 @@ - -<% user = User.find(note.user_id) %> -
    -
    -
    -
      -
    • <%= t("helpers.comments.commented_by")%>

    • -
    • <%= user.name%> (<%= l note.updated_at, format: :custom %>)
    • -
    • <%= raw note.text %>
    • -
    -
    diff --git a/app/views/plans/create.html.erb b/app/views/plans/create.html.erb new file mode 100644 index 0000000..b1ef328 --- /dev/null +++ b/app/views/plans/create.html.erb @@ -0,0 +1,14 @@ + +
    + +

    Choose one of these templates

    + +<%= debug @templates %> + +<% @templates.each do |t| %> +

    <%= t %> +<% end %> + +

    + + diff --git a/app/views/plans/edit.html.erb b/app/views/plans/edit.html.erb index 0bd9403..bd3de93 100644 --- a/app/views/plans/edit.html.erb +++ b/app/views/plans/edit.html.erb @@ -1,16 +1,19 @@ <%- model_class = Plan -%> <% javascript "plans.js" %> - + -<%= render :partial => "/projects/project_title", locals: {project: @plan.project} %> +<%= render :partial => "plan_title", locals: {plan: @plan} %> <% status = @plan.status %>
    <%space_used = status["space_used"].to_i - space_title = t("helpers.plan.export.space_used", space_used: space_used, num_pages: @plan.dmptemplate.settings(:export).max_pages) + space_title = t("helpers.plan.export.space_used", space_used: space_used, num_pages: @plan.template.settings(:export).max_pages) answered = %(#{status["num_answers"]}/#{status["num_questions"]})%>
    <%= answered -%> <%= t("helpers.project.questions_answered")%> @@ -23,27 +26,18 @@
    -<% readonly = nil %> -<% if ! @plan.editable_by(current_user.id) then %> - <% readonly = "always" %> -<% end %> - - -<%= render :partial => "/projects/project_nav_tabs", locals: {project: @plan.project, active: @plan.id} %> + +<%= render :partial => "plan_nav_tabs", locals: {plan: @plan, active: @phase.id } %> - +
    - <% sections = @plan.sections %> + <% sections = @phase.sections %> <% sections.each do |section| %> - <% locked = @plan.locked(section.id, current_user.id) %> - <% if readonly == nil && locked["locked"] then %> - <% readonly = "conditional" %> - <% end %> <% if session[:question_id_comments].to_i != 0 then %> @@ -56,59 +50,78 @@
    - <% num_section_questions = @plan.status["sections"][section.id]["num_questions"] %> - <% num_section_answers = @plan.status["sections"][section.id]["num_answers"] %> + + + <% num_section_questions = @section.status["sections"][section.id]["num_questions"] %> + <% num_section_answers = @section.status["sections"][section.id]["num_answers"] %> <% question_word = "questions" %> <% if num_section_questions == 1 then %> <% question_word = "question" %> <% end %> <% section_status = "#{num_section_questions} #{question_word}, #{num_section_answers} answered" %> + + + + -
    +
    + +
    - <%= raw section.description %> -
    + <%= raw section.description %> +
    + +

    <%= t ('helpers.loading')%>

    - -
    - + <% section.questions.order("number").each do |question| %> + <% if question.id == session[:question_id_comments].to_i then id_css = "current_question" end %> +
    + <% partialname = "answer_form" + if @readonly + partialname += "_ro" + end + %> + + <%= render partial: partialname, + locals: { + plan: @plan, + question: question, + last_question_id: section.questions.order("number DESC").first.id + } + %> +
    + <% end %> +
    + +
    + + + + +