diff --git a/app/controllers/plans_controller.rb b/app/controllers/plans_controller.rb index 89e7942..b0f3465 100644 --- a/app/controllers/plans_controller.rb +++ b/app/controllers/plans_controller.rb @@ -18,7 +18,7 @@ authorize @plan # Get all of the available funders and non-funder orgs - @funders = Org.funders.sort{|x,y| x.name <=> y.name } + @funders = Org.funders.joins(:templates).where(templates: {published: true}).uniq.sort{|x,y| x.name <=> y.name } @orgs = (Org.institutions + Org.managing_orgs).flatten.uniq.sort{|x,y| x.name <=> y.name } # Get the current user's org diff --git a/app/controllers/questions_controller.rb b/app/controllers/questions_controller.rb index 14a6d21..2beb963 100644 --- a/app/controllers/questions_controller.rb +++ b/app/controllers/questions_controller.rb @@ -4,38 +4,36 @@ #create a question def admin_create - @question = Question.new(params[:question]) - authorize @question - example = @question.annotations.first - if example.present? - example.org_id = current_user.org_id - example.example_answer! - end - if params["new-question-guidance"].present? - guidance = @question.annotations.build - guidance.text = params["new-question-guidance"] - guidance.org_id = current_user.org_id - guidance.guidance! - guidance.save - end - @question.default_value = params["new-question-default-value"] - @question.modifiable = true - if @question.save - @question.section.phase.template.dirty = true - @question.section.phase.template.save! + begin + @question = Question.new(question_params) + authorize @question + @question.modifiable = true + if @question.save + @question.section.phase.template.dirty = true + @question.section.phase.template.save! + if params[:example_answer].present? + example_answer = Annotation.new({question_id: @question.id, org_id: current_user.org_id, text: params[:example_answer], type: Annotation.types[:example_answer]}) + example_answer.save + end + if params[:guidance].present? + guidance = Annotation.new({question_id: @question.id, org_id: current_user.org_id, text: params[:guidance], type: Annotation.types[:guidance]}) + guidance.save + end + redirect_to admin_show_phase_path(id: @question.section.phase_id, section_id: @question.section_id, question_id: @question.id, edit: 'true'), notice: _('Information was successfully created.') + else + @edit = (@question.section.phase.template.org == current_user.org) + @open = true + @phase = @question.section.phase + @section = @question.section + @sections = @phase.sections + @section_id = @question.section.id + @question_id = @question.id - redirect_to admin_show_phase_path(id: @question.section.phase_id, section_id: @question.section_id, question_id: @question.id, edit: 'true'), notice: _('Information was successfully created.') - else - @edit = (@question.section.phase.template.org == current_user.org) - @open = true - @phase = @question.section.phase - @section = @question.section - @sections = @phase.sections - @section_id = @question.section.id - @question_id = @question.id - - flash[:notice] = failed_create_error(@question, _('question')) - render template: 'phases/admin_show' + flash[:notice] = failed_create_error(@question, _('question')) + render template: 'phases/admin_show' + end + rescue ActionController::ParameterMissing => e + flash[:notice] = e.message end end @@ -89,4 +87,18 @@ end end + private + # Filters the valid attributes for a question according to each type. + # Note, that params[:question] and params[:question][:question_format_id] are required and their absence raises ActionController::ParameterMissing + def question_params + permitted = params.require(:question).except(:created_at, :updated_at).tap do |question_params| + question_params.require(:question_format_id) + q_format = QuestionFormat.find(question_params[:question_format_id]) + if q_format.option_based + question_params.delete(:default_value) + else + question_params.delete(:question_options_attributes) + end + end + end end \ No newline at end of file diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index bcaf9b9..a628929 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -72,6 +72,7 @@ def update if user_signed_in? then @orgs = Org.where(parent_id: nil).order("name") + @default_org = current_user.org @other_organisations = Org.where(parent_id: nil, is_other: true).pluck(:id) @identifier_schemes = IdentifierScheme.where(active: true).order(:name) @languages = Language.sorted_by_abbreviation @@ -91,30 +92,53 @@ end def do_update(require_password = true, confirm = false) - if require_password # user is changing email or password - if current_user.email != params[:user][:email] # if user is changing email - if params[:user][:current_password].blank? # password needs to be present - message = _('Please enter your password to change email address.') - successfully_updated = false - else + mandatory_params = true + message = _('Save Unsuccessful.') + ' ' # added to by below, overwritten otherwise + # ensure that the required fields are present + if params[:user][:email].blank? + message +=_('Please enter an email address.') + ' ' + mandatory_params &&= false + end + if params[:user][:firstname].blank? + message +=_('Please enter a First name.') + ' ' + mandatory_params &&= false + end + if params[:user][:surname].blank? + message +=_('Please enter a Last name.') + ' ' + mandatory_params &&= false + end + if params[:user][:org_id].blank? + message += _('Please select an organisation, or select Other.') + mandatory_params &&= false + end + if mandatory_params # has the user entered all the details + if require_password # user is changing email or password + if current_user.email != params[:user][:email] # if user is changing email + if params[:user][:current_password].blank? # password needs to be present + message = _('Please enter your password to change email address.') + successfully_updated = false + else + successfully_updated = current_user.update_with_password(password_update) + end + elsif params[:user][:password].present? # if user is changing password + successfully_updated = false # shared across first 3 conditions + if params[:user][:current_password].blank? + message = _('Please enter your current password') + elsif params[:user][:password_confirmation].blank? + message = _('Please enter a password confirmation') + elsif params[:user][:password] != params[:user][:password_confirmation] + message = _('Password and comfirmation must match') + else + successfully_updated = current_user.update_with_password(password_update) + end + else # potentially unreachable... but I dont like to leave off the else successfully_updated = current_user.update_with_password(password_update) end - elsif params[:user][:password].present? # if user is changing password - successfully_updated = false # shared across first 3 conditions - if params[:user][:current_password].blank? - message = _('Please enter your current password') - elsif params[:user][:password_confirmation].blank? - message = _('Please enter a password confirmation') - elsif params[:user][:password] != params[:user][:password_confirmation] - message = _('Password and comfirmation must match') - else - successfully_updated = current_user.update_with_password(password_update) - end - else # potentially unreachable... but I dont like to leave off the else - successfully_updated = current_user.update_with_password(password_update) + else # password not required + successfully_updated = current_user.update_without_password(update_params) end - else # password not required - successfully_updated = current_user.update_without_password(update_params) + else + successfully_updated = false end #unlink shibboleth from user's details diff --git a/app/controllers/templates_controller.rb b/app/controllers/templates_controller.rb index c1ea7e8..817229d 100644 --- a/app/controllers/templates_controller.rb +++ b/app/controllers/templates_controller.rb @@ -14,32 +14,23 @@ funder_templates, org_templates, customizations = [], [], [] # Get all of the unique template family ids (dmptemplate_id) for each funder and the current org - funder_ids = Org.funders.includes(:templates).collect{|f| f.templates.valid.collect{|ft| ft.dmptemplate_id } }.flatten.uniq - org_ids = current_user.org.templates.valid.collect{|t| t.dmptemplate_id }.flatten.uniq + funder_ids = Org.funders.includes(:templates).collect{|f| f.templates.where(published: true).valid.collect{|ft| ft.dmptemplate_id } }.flatten.uniq + org_ids = current_user.org.templates.where(customization_of: nil).valid.collect{|t| t.dmptemplate_id }.flatten.uniq org_ids.each do |id| current = Template.current(id) live = Template.live(id) - - # If this isn't a customization of a funder template - if current.customization_of.nil? - org_templates << {current: current, live: live} - - # This is a customization of a funder template - else - funder_live = Template.live(current.customization_of) - customizations << current.customization_of - # Mark the customization as stale if the funder has a newer version - funder_templates << {current: current, live: live, stale: funder_live.updated_at > current.created_at} - end + org_templates << {current: current, live: live} end - - # Get the funder templates funder_ids.each do |id| - # If the org has a customization we don't want to load the funder version - unless customizations.include?(id) - funder_templates << {current: Template.current(id), live: Template.live(id)} - end + funder_live = Template.live(id) + current = Template.org_customizations(id, current_user.org_id) + # if we have a current template, check to see if there is a live version + live = current.nil? ? nil : Template.live(current.dmptemplate_id) + # need a current version, default to funder live if no custs exist + current = funder_live unless current.present? + + funder_templates << {current: current, live: live, funder_live: funder_live, stale: funder_live.updated_at > current.created_at} end @funder_templates = funder_templates.sort{|x,y| @@ -82,6 +73,78 @@ redirect_to admin_template_template_path(customisation) end + # GET /org/admin/templates/:id/admin_transfer_customization + # the funder template's id is passed through here + # ----------------------------------------------------- + def admin_transfer_customization + @template = Template.includes(:org).find(params[:id]) + authorize @template + new_customization = Template.deep_copy(@template) + new_customization.org_id = current_user.org_id + new_customization.published = false + new_customization.customization_of = @template.dmptemplate_id + new_customization.dirty = true + new_customization.phases.includes(sections: :questions).each do |phase| + phase.modifiable = false + phase.save + phase.sections.each do |section| + section.modifiable = false + section.save + section.questions.each do |question| + question.modifiable = false + question.save + end + end + end + customizations = Template.includes(:org, phases:[sections: [questions: :annotations]]).where(org_id: current_user.org_id, customization_of: @template.dmptemplate_id).order(version: :desc) + # existing version to port over + max_version = customizations.first + new_customization.dmptemplate_id = max_version.dmptemplate_id + new_customization.version = max_version.version + 1 + # here we rip the customizations out of the old template + # First, we find any customzed phases or sections + max_version.phases.each do |phase| + # check if the phase was added as a customization + if phase.modifiable + # deep copy the phase and add it to the template + phase_copy = Phase.deep_copy(phase) + phase_copy.number = new_customization.phases.length + 1 + phase_copy.template_id = new_customization.id + phase_copy.save! + else + # iterate over the sections to see if any of them are customizations + phase.sections.each do |section| + if section.modifiable + # this is a custom section + section_copy = Section.deep_copy(section) + customization_phase = new_customization.phases.includes(:sections.where(number: phase.number).first) + section_copy.phase_id = customization_phase.id + # custom sections get added to the end + section_copy.number = customization_phase.sections.length + 1 + # section from phase with corresponding number in the main_template + section_copy.save! + else + # not a customized section, iterate over questions + customization_phase = new_customization.phases.includes(sections: [questions: :annotations]).where(number: phase.number).first + customization_section = customization_phase.sections.where(number: section.number).first + section.questions.each do |question| + # find corresponding question in new template + customization_question = customization_section.questions.where(number: question.number).first + # apply annotations + question.annotations.each do |annotation| + annotation_copy = Annotation.deep_copy(annotation) + annotation_copy.question_id = customization_question.id + annotation_copy.save! + end + end + end + end + end + end + new_customization.save + redirect_to admin_template_template_path(new_customization) + end + # PUT /org/admin/templates/:id/admin_publish # ----------------------------------------------------- def admin_publish diff --git a/app/models/question.rb b/app/models/question.rb index 1d45c38..0a3e947 100644 --- a/app/models/question.rb +++ b/app/models/question.rb @@ -7,7 +7,7 @@ ## # Associations has_many :answers, :dependent => :destroy - has_many :question_options, :dependent => :destroy + has_many :question_options, :dependent => :destroy, :inverse_of => :question # inverse_of needed for nester forms has_many :annotations, :dependent => :destroy has_and_belongs_to_many :themes, join_table: "questions_themes" belongs_to :section diff --git a/app/models/question_format.rb b/app/models/question_format.rb index 061961a..b7d6afc 100644 --- a/app/models/question_format.rb +++ b/app/models/question_format.rb @@ -14,6 +14,9 @@ # -relies on protected_attributes gem as syntax depricated in rails 4.2 attr_accessible :title, :description, :option_based, :questions, :as => [:default, :admin] + # Retrieves the id for a given formattype passed + scope :id_for, -> (formattype) { where(formattype: formattype).pluck(:id).first } + ## # Define Bit Field Values so we can test a format without doing string comps # Column type diff --git a/app/models/template.rb b/app/models/template.rb index f0fdc00..eac8d84 100644 --- a/app/models/template.rb +++ b/app/models/template.rb @@ -44,6 +44,19 @@ end ## + # Retrieves the most current customization of the template for the + # specified org and dmptemplate_id + # returns nil if no customizations found + # + # @params [integer] dmptemplate_id of the original template + # @params [integer] org_id for the customizing organisation + # @return [nil, Template] the customized template or nil + def self.org_customizations(dmptemplate_id, org_id) + Template.where(customization_of: dmptemplate_id, org_id: org_id).order(version: :desc).valid.first + end + + + ## # deep copy the given template and all of it's associations # # @params [Template] template to be deep copied diff --git a/app/policies/template_policy.rb b/app/policies/template_policy.rb index eeda053..754e622 100644 --- a/app/policies/template_policy.rb +++ b/app/policies/template_policy.rb @@ -53,6 +53,10 @@ user.can_modify_templates? && (template.org_id == user.org_id) end + def admin_transfer_customization? + user.can_modify_templates? + end + class Scope < Scope def resolve diff --git a/app/views/annotations/_add_annotation.html.erb b/app/views/annotations/_add_annotation.html.erb index 51e62d4..8add942 100644 --- a/app/views/annotations/_add_annotation.html.erb +++ b/app/views/annotations/_add_annotation.html.erb @@ -26,7 +26,7 @@
<%= submit_tag _('Save'), class: "btn btn-primary" %> - <%= hidden_field_tag :question_id, question.id %> - <%= link_to _('Cancel'), "#", id: "cancel_add_annotations", class: "btn cancel" %> + <%= hidden_field_tag :question_id, question.id, class: "question_id" %> + <%= link_to _('Cancel'), "#", class: "btn cancel cancel_add_annotations" %>
<%end%> diff --git a/app/views/answers/_locking.html.erb b/app/views/answers/_locking.html.erb index 0bc9cc2..40a3d90 100644 --- a/app/views/answers/_locking.html.erb +++ b/app/views/answers/_locking.html.erb @@ -1,5 +1,5 @@
-

<%= _('The following answer cannot be persisted') %>

+

<%= _('The following answer cannot be saved') %>

<%= render partial: '/answers/new_edit', locals: { question: question, answer: answer, readonly: true } %>

<%= _('since %{name} saved the answer below while you were editing. Please, combine your changes and then save the answer again.') % { name: user.name} %>

diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb index 9dd7c36..0c689be 100644 --- a/app/views/devise/registrations/new.html.erb +++ b/app/views/devise/registrations/new.html.erb @@ -1,4 +1,4 @@ -

<%= _('Sign up') %>

+

<%= _('Create account') %>

<% unless session["devise.shibboleth_data"].nil? %>

<%= (_("%{application_name} doesn't recognise your institutional credentials - either you haven't created an account with us or you haven't linked these details to your existing account.
* If you do not have an account with %{application_name}, please complete the form below.
* If you have an account with %{application_name}, please Sign in so we can link your account to your institutional credentials.
Once you have created and/or linked your account, you'll be able to sign in with your institutional credentials directly.") % { :application_name => Rails.configuration.branding[:application][:name] }).html_safe %> diff --git a/app/views/home/index.html.erb b/app/views/home/index.html.erb index 40441b0..92bfeb2 100644 --- a/app/views/home/index.html.erb +++ b/app/views/home/index.html.erb @@ -38,9 +38,9 @@

- <%= _('Sign up') %> + <%= _('Create account') %>

- <%= _('New to %{application_name}? Sign up today.') % {:application_name => Rails.configuration.branding[:application][:name]} %> + <%= _('New to %{application_name}? Create an account today.') % {:application_name => Rails.configuration.branding[:application][:name]} %>

diff --git a/app/views/layouts/_footer.html.erb b/app/views/layouts/_footer.html.erb index 14cca4f..4866e06 100644 --- a/app/views/layouts/_footer.html.erb +++ b/app/views/layouts/_footer.html.erb @@ -33,7 +33,7 @@