diff --git a/app/controllers/annotations_controller.rb b/app/controllers/annotations_controller.rb
index 5e3b826..9191895 100644
--- a/app/controllers/annotations_controller.rb
+++ b/app/controllers/annotations_controller.rb
@@ -19,7 +19,8 @@
template.dirty = true
template.save!
end
- redirect_to "#{admin_show_phase_path(question.section.phase.id)}?section_id=#{question.section.id}"
+ tab = params[:r] || 'all-templates'
+ redirect_to "#{admin_show_phase_path(question.section.phase.id)}?section_id=#{question.section.id}&r=#{tab}"
end
#delete an annotation
@@ -35,7 +36,8 @@
flash[:alert] = failed_destroy_error(annotation, type)
end
end
- redirect_to "#{admin_show_phase_path(parent_ids[0])}?section_id=#{parent_ids[1]}"
+ tab = params[:r] || 'all-templates'
+ redirect_to "#{admin_show_phase_path(parent_ids[0])}?section_id=#{parent_ids[1]}&r=#{tab}"
end
private
diff --git a/app/controllers/answers_controller.rb b/app/controllers/answers_controller.rb
index a657eb5..9c9f70e 100644
--- a/app/controllers/answers_controller.rb
+++ b/app/controllers/answers_controller.rb
@@ -19,6 +19,7 @@
{ msg: _('There is no plan with id %{id} for which to create or update an answer') %{ :id => p_params[:plan_id] }})
return
end
+ q = Question.find(p_params[:question_id])
Answer.transaction do
begin
@@ -28,10 +29,17 @@
if p_params[:question_option_ids].present?
@answer.touch() # Saves the record with the updated_at set to the current time. Needed if only answer.question_options is updated
end
+ if q.question_format.rda_metadata?
+ @answer.update_answer_hash(JSON.parse(params[:standards]), p_params[:text])
+ @answer.save!
+ end
rescue ActiveRecord::RecordNotFound
@answer = Answer.new(p_params.merge({ user_id: current_user.id }))
@answer.lock_version = 1
authorize @answer
+ if q.question_format.rda_metadata?
+ @answer.update_answer_hash(JSON.parse(params[:standards]), p_params[:text])
+ end
@answer.save!
rescue ActiveRecord::StaleObjectError
@stale_answer = @answer
diff --git a/app/controllers/concerns/paginable.rb b/app/controllers/concerns/paginable.rb
index dea6bb3..76340d3 100644
--- a/app/controllers/concerns/paginable.rb
+++ b/app/controllers/concerns/paginable.rb
@@ -7,15 +7,18 @@
# controller {String} - Represents the name of the controller to handles the pagination
# action {String} - Represents the method name within the controller
# path_params {Hash} - A hash of additional URL path parameters (e.g. path_paths = { id: 'foo' } for /paginable/templates/:id/history/:page)
+ # query_params {Hash} - A hash of query parameters used to merge with params object from the controller for which this concern is included
# scope {ActiveRecord::Relation} - Represents scope variable
# locals {Hash} - A hash objects with any additional local variables to be passed to the partial view
- def paginable_renderise(partial: nil, controller: params[:controller], action: params[:action], path_params: {}, scope: nil, locals: {})
+ def paginable_renderise(partial: nil, controller: params[:controller], action: params[:action], path_params: {}, query_params: {}, scope: nil, locals: {})
raise ArgumentError, 'scope should be an ActiveRecord::Relation object' unless scope.is_a?(ActiveRecord::Relation)
raise ArgumentError, 'path_params should be a Hash object' unless path_params.is_a?(Hash)
+ raise ArgumentError, 'query_params should be a Hash object' unless query_params.is_a?(Hash)
raise ArgumentError, 'locals should be a Hash object' unless locals.is_a?(Hash)
@paginable_controller = controller
@paginable_action = action
@paginable_path_params = path_params
+ merge_query_params(query_params)
refined_scope = refine_query(scope)
render(layout: "/layouts/paginable", partial: partial, locals: {
controller: controller,
@@ -39,7 +42,7 @@
end
# Determines whether or not the latest request included the search functionality
def searchable?
- return params.present? && params[:search].present?
+ return params[:search].present?
end
# Generates an HTML link with search functionality (if latest request included the search functionality)
# text {String} - Represents the text for the searchable link
@@ -51,10 +54,20 @@
end
end
private
+ # Attemps to merge query_params into params hash unless a key is already present at params
+ def merge_query_params(query_params = {})
+ query_params.each_pair.reduce(params) do |m, o|
+ key = o[0].to_sym
+ if m[key].nil?
+ m[key] = o[1].to_s
+ end
+ m
+ end
+ end
# Returns the upcase string (e.g ASC or DESC) if sort_direction param is present in any of the forms 'asc', 'desc', 'ASC', 'DESC'
# otherwise returns nil
def sort_direction
- if params.present? && params[:sort_direction].present?
+ if params[:sort_direction].present?
directions = ['asc', 'desc', 'ASC', 'DESC']
return directions.include?(params[:sort_direction]) ? params[:sort_direction].upcase : 'ASC'
end
@@ -67,15 +80,13 @@
end
# Refine a scope passed to this concern if any of the params (search, sort_field or page) are present
def refine_query(scope)
- if params.present?
- scope = scope.search(params[:search]) if params[:search].present? # Can raise NoMethodError if the scope does not define a search method
- if params[:sort_field].present?
- direction = sort_direction
- scope = direction.present? ? scope.order("#{params[:sort_field]} #{direction}") : scope.order("#{params[:sort_field]}") # Can raise ActiveRecord::StatementInvalid (e.g. column does not exist, ambiguity on column, etc)
- end
- if params[:page] != 'ALL'
- scope = scope.page(params[:page]) # Can raise error if page is not a number
- end
+ scope = scope.search(params[:search]) if params[:search].present? # Can raise NoMethodError if the scope does not define a search method
+ if params[:sort_field].present?
+ direction = sort_direction
+ scope = direction.present? ? scope.order("#{params[:sort_field]} #{direction}") : scope.order("#{params[:sort_field]}") # Can raise ActiveRecord::StatementInvalid (e.g. column does not exist, ambiguity on column, etc)
+ end
+ if params[:page] != 'ALL'
+ scope = scope.page(params[:page]) # Can raise error if page is not a number
end
return scope
end
@@ -86,20 +97,19 @@
if direction.present? && params[:sort_field] == sort_field
className = direction == 'ASC'? 'fa-sort-asc' : 'fa-sort-desc'
end
- return raw("")
+ return raw("")
end
# Returns the sort url for a given sort_field.
def sort_link_url(sort_field)
- url = paginable_base_url(1)+"?"
+ page = params[:page] == 'ALL' ? 'ALL' : 1 # Retain ALL param page if latest request included it
+ url = paginable_base_url(page)+"?"
query_string = []
- if params.present?
- query_string << "search=#{params[:search]}" if params[:search].present?
- direction = sort_direction
- if direction.present? && params[:sort_field] == sort_field
- query_string << "sort_direction=#{swap_sort_direction(direction)}"
- else
- query_string << "sort_direction=ASC"
- end
+ query_string << "search=#{params[:search]}" if params[:search].present?
+ direction = sort_direction
+ if direction.present? && params[:sort_field] == sort_field
+ query_string << "sort_direction=#{swap_sort_direction(direction)}"
+ else
+ query_string << "sort_direction=ASC"
end
query_string << "sort_field=#{sort_field}"
return url+query_string.join('&')
diff --git a/app/controllers/guidances_controller.rb b/app/controllers/guidances_controller.rb
index 6351b7c..357889f 100644
--- a/app/controllers/guidances_controller.rb
+++ b/app/controllers/guidances_controller.rb
@@ -67,8 +67,10 @@
authorize guidance
guidance.text = params["guidance-text"]
- if guidance.update_attributes(guidance_params)
-
+ attrs = guidance_params
+ attrs[:theme_ids] = [] unless attrs[:theme_ids]
+
+ if guidance.update_attributes(attrs)
if guidance.published?
guidance_group = GuidanceGroup.find(guidance.guidance_group_id)
if !guidance_group.published? || guidance_group.published.nil?
diff --git a/app/controllers/notes_controller.rb b/app/controllers/notes_controller.rb
index 996ed7b..94386d9 100644
--- a/app/controllers/notes_controller.rb
+++ b/app/controllers/notes_controller.rb
@@ -40,7 +40,7 @@
plan = answer.plan
owner = plan.owner
deliver_if(recipients: owner, key: 'users.new_comment') do |r|
- UserMailer.new_comment(r, plan).deliver_now()
+ UserMailer.new_comment(current_user, plan).deliver_now()
end
@notice = success_message(_('comment'), _('created'))
render(json: {
diff --git a/app/controllers/org_admin/plans_controller.rb b/app/controllers/org_admin/plans_controller.rb
index 9a303d6..b8bd89d 100644
--- a/app/controllers/org_admin/plans_controller.rb
+++ b/app/controllers/org_admin/plans_controller.rb
@@ -43,7 +43,7 @@
plans = CSV.generate do |csv|
csv << header_cols
- org.plans.includes(template: :org).each do |plan|
+ org.plans.includes(template: :org).order(updated_at: :desc).each do |plan|
owner = plan.owner
csv << [
"#{plan.title}",
diff --git a/app/controllers/org_admin/templates_controller.rb b/app/controllers/org_admin/templates_controller.rb
index 54930c9..158016e 100644
--- a/app/controllers/org_admin/templates_controller.rb
+++ b/app/controllers/org_admin/templates_controller.rb
@@ -30,7 +30,7 @@
published: published,
current_org: current_user.org,
orgs: Org.all,
- current_tab: params[:r] || 'all-templates',
+ current_tab: params[:r],
scopes: { all: all_templates_hash[:scopes], orgs: own_hash[:scopes], funders: customizable_hash[:scopes] }
}
end
@@ -53,10 +53,10 @@
@template.links = (params["template-links"].present? ? JSON.parse(params["template-links"]) : {"funder": [], "sample_plan": []})
if @template.save
- redirect_to edit_org_admin_template_path(@template), notice: success_message(_('template'), _('created'))
+ redirect_to edit_org_admin_template_path(@template), notice: success_message(@template.template_type, _('created'))
else
@hash = @template.to_hash
- flash[:alert] = failed_create_error(@template, _('template'))
+ flash[:alert] = failed_create_error(@template, @template.template_type)
render action: "new"
end
end
@@ -68,30 +68,31 @@
authorize @template
@current = Template.current(@template.dmptemplate_id)
-
+ @current_tab = params[:r] || 'all-templates'
+
if @template == @current
if @template.published?
new_version = @template.get_new_version
if !new_version.nil?
- redirect_to(action: 'edit', id: new_version.id)
+ redirect_to(action: 'edit', id: new_version.id, r: @current_tab)
return
else
- flash[:alert] = _('Unable to create a new version of this template. You are currently working with a published copy.')
+ flash[:alert] = _("Unable to create a new version of this #{@template.template_type}. You are currently working with a published copy.")
end
end
else
- flash[:notice] = _('You are viewing a historical version of this template. You will not be able to make changes.')
+ flash[:notice] = _("You are viewing a historical version of this #{@template.template_type}. You will not be able to make changes.")
end
# once the correct template has been generated, we convert it to hash
@template_hash = @template.to_hash
- @current_tab = params[:r] || 'all-templates'
render('container',
locals: {
partial_path: 'edit',
template: @template,
current: @current,
+ edit: @template == @current,
template_hash: @template_hash,
current_tab: @current_tab
})
@@ -107,13 +108,13 @@
# Only allow the current version to be updated
if current != @template
- render(status: :forbidden, json: { msg: _('You can not edit a historical version of this template.')})
+ render(status: :forbidden, json: { msg: _("You can not edit a historical version of this #{@template.template_type}.")})
else
template_links = nil
begin
template_links = JSON.parse(params["template-links"]) if params["template-links"].present?
rescue JSON::ParserError
- render(status: :bad_request, json: { msg: _('Error parsing links for a template') })
+ render(status: :bad_request, json: { msg: _("Error parsing links for a #{@template.template_type}") })
return
end
@@ -136,10 +137,10 @@
end
if @template.update_attributes(params[:template])
- render(status: :ok, json: { msg: success_message(_('template'), _('saved'))})
+ render(status: :ok, json: { msg: success_message(@template.template_type, _('saved'))})
else
# Note failed_update_error may return HTML tags (e.g. ) and therefore the client should parse them accordingly
- render(status: :bad_request, json: { msg: failed_update_error(@template, _('template'))})
+ render(status: :bad_request, json: { msg: failed_update_error(@template, @template.template_type)})
end
end
end
@@ -157,19 +158,19 @@
# Only allow the current version to be destroyed
if current == @template
if @template.destroy
- flash[:notice] = success_message(_('template'), _('removed'))
+ flash[:notice] = success_message(@template.template_type, _('removed'))
redirect_to org_admin_templates_path(r: current_tab)
else
@hash = @template.to_hash
- flash[:alert] = failed_destroy_error(@template, _('template'))
+ flash[:alert] = failed_destroy_error(@template, @template.template_type)
redirect_to org_admin_templates_path(r: current_tab)
end
else
- flash[:alert] = _('You cannot delete historical versions of this template.')
+ flash[:alert] = _("You cannot delete historical versions of this #{@template.template_type}.")
redirect_to org_admin_templates_path(r: current_tab)
end
else
- flash[:alert] = _('You cannot delete a template that has been used to create plans.')
+ flash[:alert] = _("You cannot delete a #{@template.template_type} that has been used to create plans.")
redirect_to org_admin_templates_path(r: current_tab)
end
end
@@ -179,7 +180,7 @@
def history
@template = Template.find(params[:id])
authorize @template
- @templates = Template.where(dmptemplate_id: @template.dmptemplate_id).order(version: :desc)
+ @templates = Template.where(dmptemplate_id: @template.dmptemplate_id)
@current = Template.current(@template.dmptemplate_id)
@current_tab = params[:r] || 'all-templates'
end
@@ -308,10 +309,10 @@
end
if new_copy.save
- flash[:notice] = 'Template was successfully copied.'
+ flash[:notice] = "#{@template.template_type.capitalize} was successfully copied."
redirect_to edit_org_admin_template_path(id: new_copy.id, edit: true, r: 'organisation-templates'), notice: _('Information was successfully created.')
else
- flash[:alert] = failed_create_error(new_copy, _('template'))
+ flash[:alert] = failed_create_error(new_copy, @template.template_type)
end
end
@@ -321,12 +322,11 @@
def publish
template = Template.find(params[:id])
authorize template
-
current = Template.current(template.dmptemplate_id)
# Only allow the current version to be updated
if current != template
- redirect_to org_admin_templates_path, alert: _('You can not publish a historical version of this template.')
+ redirect_to org_admin_templates_path, alert: _("You can not publish a historical version of this #{template.template_type}.")
else
# Unpublish the older published version if there is one
@@ -340,8 +340,8 @@
template.published = true
template.save
- flash[:notice] = _('Your template has been published and is now available to users.')
- redirect_to "#{org_admin_templates_path}#{template.customization_of.present? ? '#funder-templates' : '#organisation-templates'}"
+ flash[:notice] = _("Your #{template.template_type} has been published and is now available to users.")
+ redirect_to "#{org_admin_templates_path}#{template.template_type == 'customisation' ? '#funder-templates' : '#organisation-templates'}"
end
end
@@ -352,14 +352,14 @@
authorize template
if template.nil?
- flash[:alert] = _('That template is not currently published.')
+ flash[:alert] = _("That #{template.template_type} is not currently published.")
else
template.published = false
template.save
- flash[:notice] = _('Your template is no longer published. Users will not be able to create new DMPs for this template until you re-publish it')
+ flash[:notice] = _("Your #{template.template_type} is no longer published. Users will not be able to create new DMPs for this #{template.template_type} until you re-publish it")
end
- redirect_to "#{org_admin_templates_path}#{template.customization_of.present? ? '#funder-templates' : '#organisation-templates'}"
+ redirect_to "#{org_admin_templates_path}#{template.template_type == 'customisation' ? '#funder-templates' : '#organisation-templates'}"
end
# PUT /org_admin/template_options (AJAX)
diff --git a/app/controllers/paginable/orgs_controller.rb b/app/controllers/paginable/orgs_controller.rb
index 16bd7df..fc78fa6 100644
--- a/app/controllers/paginable/orgs_controller.rb
+++ b/app/controllers/paginable/orgs_controller.rb
@@ -5,7 +5,7 @@
authorize(Org)
paginable_renderise(
partial: 'index',
- scope: Org.includes(:templates, :users).joins(:templates, :users)
- )
+ scope: Org.includes(:templates, :users),
+ query_params: { sort_field: 'orgs.name', sort_direction: :asc })
end
end
diff --git a/app/controllers/paginable/plans_controller.rb b/app/controllers/paginable/plans_controller.rb
index d691dda..8d29990 100644
--- a/app/controllers/paginable/plans_controller.rb
+++ b/app/controllers/paginable/plans_controller.rb
@@ -9,7 +9,8 @@
def organisationally_or_publicly_visible
raise Pundit::NotAuthorizedError unless Paginable::PlanPolicy.new(current_user).organisationally_or_publicly_visible?
paginable_renderise(partial: 'organisationally_or_publicly_visible',
- scope: Plan.organisationally_or_publicly_visible(current_user))
+ scope: Plan.organisationally_or_publicly_visible(current_user),
+ query_params: { sort_field: 'plans.title', sort_direction: :asc })
end
# GET /paginable/plans/publicly_visible/:page
def publicly_visible
diff --git a/app/controllers/paginable/templates_controller.rb b/app/controllers/paginable/templates_controller.rb
index 62cede2..b3370c1 100644
--- a/app/controllers/paginable/templates_controller.rb
+++ b/app/controllers/paginable/templates_controller.rb
@@ -86,6 +86,7 @@
paginable_renderise(
partial: 'history',
scope: @templates,
+ query_params: { sort_field: :version, sort_direction: :desc },
locals: { current: @current })
end
end
diff --git a/app/controllers/phases_controller.rb b/app/controllers/phases_controller.rb
index 3d10ca9..14e3210 100644
--- a/app/controllers/phases_controller.rb
+++ b/app/controllers/phases_controller.rb
@@ -43,7 +43,7 @@
#show and edit a phase of the template
def admin_show
- @phase = Phase.includes(:sections).order(:number).find(params[:id])
+ @phase = Phase.includes(:template, :sections).order(:number).find(params[:id])
authorize @phase
@current = Template.current(@phase.template.dmptemplate_id)
@@ -58,6 +58,10 @@
@original_org = @phase.template.org
end
+ if @phase.template != @current
+ flash[:notice] = _('You are viewing a historical version of this template. You will not be able to make changes.')
+ end
+
render('/org_admin/templates/container',
locals: {
partial_path: 'admin_show',
@@ -90,6 +94,7 @@
locals: {
partial_path: 'admin_add',
template: @template,
+ edit: true,
current_tab: params[:r] || 'all-templates'
})
end
diff --git a/app/controllers/plans_controller.rb b/app/controllers/plans_controller.rb
index fddb1e9..48b544d 100644
--- a/app/controllers/plans_controller.rb
+++ b/app/controllers/plans_controller.rb
@@ -8,7 +8,7 @@
def index
authorize Plan
@plans = Plan.active(current_user).page(1)
- @organisationally_or_publicly_visible = Plan.organisationally_or_publicly_visible(current_user).order(:title => :asc).page(1)
+ @organisationally_or_publicly_visible = Plan.organisationally_or_publicly_visible(current_user).page(1)
end
# GET /plans/new
@@ -156,18 +156,26 @@
authorize @plan
attrs = plan_params
- # Save the guidance group selections
- guidance_group_ids = params[:guidance_group_ids].blank? ? [] : params[:guidance_group_ids].map(&:to_i).uniq
- save_guidance_selections(guidance_group_ids)
-
respond_to do |format|
- if @plan.update_attributes(attrs)
- format.html { redirect_to @plan, :editing => false, notice: success_message(_('plan'), _('saved')) }
- format.json {render json: {code: 1, msg: success_message(_('plan'), _('saved'))}}
- else
+ begin
+ # Save the guidance group selections
+ guidance_group_ids = params[:guidance_group_ids].blank? ? [] : params[:guidance_group_ids].map(&:to_i).uniq
+ @plan.guidance_groups = GuidanceGroup.where(id: guidance_group_ids)
+ @plan.save
+
+ if @plan.update_attributes(attrs)
+ format.html { redirect_to @plan, :editing => false, notice: success_message(_('plan'), _('saved')) }
+ format.json {render json: {code: 1, msg: success_message(_('plan'), _('saved'))}}
+ else
+ flash[:alert] = failed_update_error(@plan, _('plan'))
+ format.html { render action: "edit" }
+ format.json {render json: {code: 0, msg: flash[:alert]}}
+ end
+
+ rescue Exception
flash[:alert] = failed_update_error(@plan, _('plan'))
format.html { render action: "edit" }
- format.json {render json: {code: 0, msg: failed_update_error(@plan, _('plan'))}}
+ format.json {render json: {code: 0, msg: flash[:alert]}}
end
end
end
@@ -243,21 +251,21 @@
@public_plan = false
@hash = @plan.as_pdf(@show_coversheet)
- @formatting = @plan.settings(:export).formatting
+ @formatting = params[:export][:formatting] || @plan.settings(:export).formatting
file_name = @plan.title.gsub(/ /, "_")
respond_to do |format|
format.html { render layout: false }
format.csv { send_data @plan.as_csv(@show_sections_questions), filename: "#{file_name}.csv" }
format.text { send_data render_to_string(partial: 'shared/export/plan_txt'), filename: "#{file_name}.txt" }
- format.docx { render docx: 'export', filename: "#{file_name}.docx" }
+ format.docx { render docx: "#{file_name}.docx", content: render_to_string(partial: 'shared/export/plan') }
format.pdf do
render pdf: file_name,
margin: @formatting[:margin],
footer: {
center: _('Created using the %{application_name}. Last modified %{date}') % {application_name: Rails.configuration.branding[:application][:name], date: l(@plan.updated_at.to_date, formats: :short)},
font_size: 8,
- spacing: (@formatting[:margin][:bottom] / 2) - 4,
+ spacing: (Integer(@formatting[:margin][:bottom]) / 2) - 4,
right: '[page] of [topage]'
}
end
@@ -350,25 +358,6 @@
:data_contact, :data_contact_email, :data_contact_phone, :guidance_group_ids)
end
- def save_guidance_selections(guidance_group_ids)
- all_guidance_groups = @plan.get_guidance_group_options
- plan_groups = @plan.guidance_groups
- guidance_groups = GuidanceGroup.where(id: guidance_group_ids)
- all_guidance_groups.each do |group|
- # case where plan group exists but not in selection
- if plan_groups.include?(group) && ! guidance_groups.include?(group)
- # remove from plan groups
- @plan.guidance_groups.delete(group)
- end
- # case where plan group dosent exist and in selection
- if !plan_groups.include?(group) && guidance_groups.include?(group)
- # add to plan groups
- @plan.guidance_groups << group
- end
- end
- @plan.save
- end
-
# different versions of the same template have the same dmptemplate_id
# but different version numbers so for each set of templates with the
diff --git a/app/controllers/question_formats_controller.rb b/app/controllers/question_formats_controller.rb
new file mode 100644
index 0000000..ced3624
--- /dev/null
+++ b/app/controllers/question_formats_controller.rb
@@ -0,0 +1,10 @@
+class QuestionFormatsController < ApplicationController
+ # do we need authorizaton on this? it will only return the URL for the rda api
+ # down the line we will add more methods for other external api's
+ def rda_api_address
+ render json: {
+ 'url' => QuestionFormat.rda_metadata.first.description
+ }.to_json
+ end
+
+end
diff --git a/app/controllers/questions_controller.rb b/app/controllers/questions_controller.rb
index 44a73cb..292d970 100644
--- a/app/controllers/questions_controller.rb
+++ b/app/controllers/questions_controller.rb
@@ -85,7 +85,11 @@
@section = @question.section
@phase = @section.phase
template = @phase.template
- if @question.update_attributes(params[:question])
+
+ attrs = params[:question]
+ attrs[:theme_ids] = [] unless attrs[:theme_ids]
+
+ if @question.update_attributes(attrs)
@phase.template.dirty = true
@phase.template.save!
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index 7984224..aa0380d 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -52,13 +52,13 @@
else
existing_user = User.where_case_insensitive('email', sign_up_params[:email]).first
if existing_user.present?
- if existing_user.accept_terms?
+ if existing_user.invitation_token.present? && !existing_user.accept_terms?
+ existing_user.destroy # Destroys the existing user since the accept terms are nil/false. and they have an invitation
+ # Note any existing role for that user will be deleted too. Added to accommodate issue at:
+ # https://github.com/DMPRoadmap/roadmap/issues/322 when invited user creates an account outside the invite workflow
+ else
redirect_to after_sign_up_error_path_for(resource), alert: _('That email address is already registered.')
return
- else
- existing_user.destroy # Destroys the existing user since the accept terms are nil/false.
- # Note any existing role for that user will be deleted too. Added to accommodate issue at:
- # https://github.com/DMPRoadmap/roadmap/issues/322
end
end
if params[:user][:org_id].blank?
@@ -155,10 +155,10 @@
else
successfully_updated = current_user.update_with_password(password_update)
end
- else # user did not change their email so no pwd required
+ else # This case is never reached since this method when called with require_password = true is because the email changed. The case for password changed goes to do_update_password instead
successfully_updated = current_user.update_without_password(update_params)
end
- else # password not required
+ else # password not required
successfully_updated = current_user.update_without_password(update_params)
end
else
@@ -203,7 +203,7 @@
session[:locale] = current_user.get_locale unless current_user.get_locale.nil?
set_gettext_locale #Method defined at controllers/application_controller.rb
set_flash_message :notice, success_message(_('password'), _('saved'))
- sign_in current_user, bypass: true # Sign in the user bypassing validation in case his password changed
+ sign_in current_user, bypass: true # TODO this method is deprecated
redirect_to "#{edit_user_registration_path}\#password-details", notice: success_message(_('password'), _('saved'))
else
diff --git a/app/controllers/super_admin/orgs_controller.rb b/app/controllers/super_admin/orgs_controller.rb
index 014fa72..72d338b 100644
--- a/app/controllers/super_admin/orgs_controller.rb
+++ b/app/controllers/super_admin/orgs_controller.rb
@@ -4,7 +4,7 @@
def index
authorize Org
- render 'index', locals: { orgs: Org.includes(:templates, :users).joins(:templates, :users).order('orgs.name') }
+ render 'index', locals: { orgs: Org.includes(:templates, :users) }
end
def new
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 1d1e2fe..992c6ab 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -30,6 +30,10 @@
end
end
+ def is_integer?(string)
+ return string.present? && string.match(/^(\d)+$/)
+ end
+
def fingerprinted_asset(name)
Rails.env.production? ? "#{name}-#{ASSET_FINGERPRINT}" : name
end
diff --git a/app/models/answer.rb b/app/models/answer.rb
index c9e3d6c..a2a625f 100644
--- a/app/models/answer.rb
+++ b/app/models/answer.rb
@@ -10,9 +10,9 @@
else
plan.touch # Force updated_at changes if nothing changed since save only saves if changes were made to the record
end
- end
+ end
end
-
+
##
# Associations
belongs_to :question
@@ -63,7 +63,7 @@
answer_copy.save!
return answer_copy
end
-
+
# This method helps to decide if an answer option (:radiobuttons, :checkbox, etc ) in form views should be checked or not
# Returns true if the given option_id is present in question_options, otherwise returns false
def has_question_option(option_id)
@@ -86,4 +86,37 @@
def non_archived_notes
return notes.select{ |n| n.archived.blank? }.sort!{ |x,y| y.updated_at <=> x.updated_at }
end
+
+
+ ##
+ # Returns the parsed JSON hash for the current answer object
+ # Generates a new hash if none exists for rda_questions
+ #
+ # @return [Hash] the parsed hash of the answer.
+ # Should have keys 'standards', 'text'
+ # 'standards' is a list of : pairs
+ # 'text' is the text from the comments box
+ def answer_hash
+ default = {'standards' => {}, 'text' => ''}
+ begin
+ h = self.text.nil? ? default : JSON.parse(self.text)
+ rescue JSON::ParserError => e
+ h = default
+ end
+ return h
+ end
+
+ ##
+ # Given a hash of standards and a comment value, this updates answer
+ # text for rda_questions
+ #
+ # @param [standards] a hash of standards
+ # @param [text] option comment text
+ # nothing returned, but the status of the text field of the answer is changed
+ def update_answer_hash(standards={},text="")
+ h = {}
+ h['standards'] = standards
+ h['text'] = text
+ self.text = h.to_json
+ end
end
diff --git a/app/models/concerns/exportable_plan.rb b/app/models/concerns/exportable_plan.rb
index fe34e50..c55aa2f 100644
--- a/app/models/concerns/exportable_plan.rb
+++ b/app/models/concerns/exportable_plan.rb
@@ -1,15 +1,15 @@
module ExportablePlan
extend ActiveSupport::Concern
-
+
included do
-
+
def as_pdf(coversheet = false)
prepare(coversheet)
end
-
+
def as_csv(headings = true, unanswered = true)
hash = prepare(false)
-
+
CSV.generate do |csv|
hdrs = (hash[:phases].length > 1 ? [_('Phase')] : [])
if headings
@@ -17,7 +17,7 @@
else
csv << _('Answer')
end
-
+
csv << hdrs.flatten
hash[:phases].each do |phase|
phase[:sections].each do |section|
@@ -31,24 +31,24 @@
else
flds << [ sanitize_text(answer_text) ]
end
-
+
csv << flds.flatten
end
end
end
end
end
-
- private
+
+ private
def prepare(coversheet = false)
hash = coversheet ? prepare_coversheet : {}
template = Template.includes(phases: { sections: {questions: :question_format } }).
joins(phases: { sections: { questions: :question_format } }).
where(id: self.template_id).first
-
+
hash[:title] = self.title
hash[:answers] = self.answers
-
+
# add the relevant questions/answers
phases = []
template.phases.each do |phase|
@@ -65,19 +65,19 @@
else
txt << question.text
end
- sctn[:questions] << { id: question.id, text: txt }
+ sctn[:questions] << { id: question.id, text: txt, format: question.question_format }
end
phs[:sections] << sctn
end
phases << phs
end
hash[:phases] = phases
-
+
record_plan_export(:pdf)
-
+
hash
end
-
+
def prepare_coversheet
hash = {}
# name of owner and any co-owners
@@ -86,10 +86,10 @@
attribution << role.user.name(false)
end
hash[:attribution] = attribution
-
+
# Org name of plan owner's org
hash[:affiliation] = self.owner.present? ? self.owner.org.name : ''
-
+
# set the funder name
hash[:funder] = self.funder_name.present? ? self.funder_name : (self.template.org.present? ? self.template.org.name : '')
@@ -104,7 +104,7 @@
hash[:customizer] = customizer
hash
end
-
+
def record_plan_export(format)
exported_plan = ExportedPlan.new.tap do |ep|
ep.plan = self
@@ -118,9 +118,9 @@
end
exported_plan.save
end
-
+
def sanitize_text(text)
if (!text.nil?) then ActionView::Base.full_sanitizer.sanitize(text.gsub(/ /i,"")) end
end
end
-end
\ No newline at end of file
+end
diff --git a/app/models/exported_plan.rb b/app/models/exported_plan.rb
index bc42e4b..bb79837 100644
--- a/app/models/exported_plan.rb
+++ b/app/models/exported_plan.rb
@@ -11,11 +11,11 @@
VALID_FORMATS = ['csv', 'html', 'pdf', 'text', 'docx']
- validates :format, inclusion: {
+ validates :format, inclusion: {
in: VALID_FORMATS,
- message: -> (object, data) do
- _('%{value} is not a valid format') % { :value => data[:value] }
- end
+ message: -> (object, data) do
+ _('%{value} is not a valid format') % { :value => data[:value] }
+ end
}
validates :plan, :format, presence: {message: _("can't be blank")}
diff --git a/app/models/org.rb b/app/models/org.rb
index 960d2e1..dee239c 100644
--- a/app/models/org.rb
+++ b/app/models/org.rb
@@ -151,7 +151,7 @@
end
def grant_api!(token_permission_type)
- org.token_permission_types << token_permission_type unless org.tokenpermission_types.include? token_permission_type
+ self.token_permission_types << token_permission_type unless self.token_permission_types.include? token_permission_type
end
private
diff --git a/app/models/plan.rb b/app/models/plan.rb
index 9ef0a14..431ceac 100644
--- a/app/models/plan.rb
+++ b/app/models/plan.rb
@@ -218,7 +218,8 @@
if self.save!
# Send an email confirmation to the owners and co-owners
- deliver_if(recipients: self.owner_and_coowners, key: 'users.feedback_requested') do |r|
+ owners = User.joins(:roles).where('roles.plan_id =? AND roles.access IN (?)', self.id, Role.access_values_for(:administrator))
+ deliver_if(recipients: owners, key: 'users.feedback_requested') do |r|
UserMailer.feedback_confirmation(r, self, user).deliver_now
end
# Send an email to all of the org admins as well as the Org's administrator email
@@ -255,8 +256,9 @@
if self.save!
# Send an email confirmation to the owners and co-owners
- deliver_if(recipients: self.owner_and_coowners, key: 'users.feedback_provided') do |r|
- UserMailer.feedback_notification(r, self, org_admin).deliver_now
+ owners = User.joins(:roles).where('roles.plan_id =? AND roles.access IN (?)', self.id, Role.access_values_for(:administrator))
+ deliver_if(recipients: owners, key: 'users.feedback_provided') do |r|
+ UserMailer.feedback_complete(r, self, org_admin).deliver_now
end
true
else
diff --git a/app/models/question_format.rb b/app/models/question_format.rb
index b7d6afc..b6d1e36 100644
--- a/app/models/question_format.rb
+++ b/app/models/question_format.rb
@@ -4,11 +4,11 @@
# Associations
has_many :questions
- enum formattype: [ :textarea, :textfield, :radiobuttons, :checkbox, :dropdown, :multiselectbox, :date ]
+ enum formattype: [ :textarea, :textfield, :radiobuttons, :checkbox, :dropdown, :multiselectbox, :date, :rda_metadata ]
attr_accessible :formattype
-
+
validates :title, presence: {message: _("can't be blank")}, uniqueness: {message: _("must be unique")}
-
+
##
# Possibly needed for active_admin
# -relies on protected_attributes gem as syntax depricated in rails 4.2
@@ -16,7 +16,7 @@
# 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 0da0b23..21e5b9c 100644
--- a/app/models/template.rb
+++ b/app/models/template.rb
@@ -169,6 +169,7 @@
new_version.version = (self.version + 1)
new_version.published = false
new_version.visibility = self.visibility # do not change the visibility
+ new_version.is_default = self.is_default # retain the default template flag
new_version.save!
new_version
else
@@ -253,6 +254,10 @@
end
return !modifiable
end
+
+ def template_type
+ self.customization_of.present? ? _('customisation') : _('template')
+ end
# --------------------------------------------------------
private
@@ -264,7 +269,7 @@
self.migrated = false
self.dirty = false
self.visibility = 0 # Organisationally visible by default
- self.is_default = false
+ self.is_default = false if self.is_default.nil?
self.version = 0 if self.version.nil?
self.visibility = Template.visibilities[:organisationally_visible] if self.visibility.nil?
diff --git a/app/models/user.rb b/app/models/user.rb
index e0eedf1..2090de0 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -65,6 +65,8 @@
end
}
+ after_update :when_org_changes
+
# EVALUATE CLASS AND INSTANCE METHODS BELOW
#
# What do they do? do they do it efficiently, and do we need them?
@@ -114,29 +116,6 @@
user_identifiers.where(identifier_scheme: scheme).first
end
-# TODO: Check the logic here. Its deleting the permissions if the user does not have permission
-# to change orgs and either the incoming or existing org is nil.
-# We should also NOT be auto-saving here!!!
- ##
- # sets a new organisation id for the user
- # if the user has any perms such as org_admin or admin, those are removed
- # if the user had an api_token, that is removed
- #
- # @param new_organisation_id [Integer] the id for an organisation
- # @return [String] the empty string as a causality of setting api_token
- def org_id=(new_org_id)
- puts "$$$$ new_org_id: #{new_org_id}"
- unless self.can_change_org? || new_org_id.nil? || self.org.nil? || (new_org_id.to_s == self.org.id.to_s)
- # rip all permissions from the user
- self.perms.delete_all
- end
- # set the user's new organisation
- super(new_org_id)
- # self.save!
- # rip api permissions from the user
- self.remove_token!
- end
-
##
# sets a new organisation for the user
#
@@ -236,8 +215,7 @@
# modifies the user model
def remove_token!
unless api_token.blank?
- self.api_token = ""
- self.save!
+ update_column(:api_token, "") unless new_record?
end
end
@@ -250,7 +228,7 @@
random_token = SecureRandom.urlsafe_base64(nil, false)
break random_token unless User.exists?(api_token: random_token)
end
- self.save!
+ update_column(:api_token, api_token) unless new_record?
deliver_if(recipients: self, key: 'users.admin_privileges') do |r|
UserMailer.api_token_granted_notification(r).deliver_now
end
@@ -310,4 +288,14 @@
def self.where_case_insensitive(field, val)
User.where("lower(#{field}) = ?", val.respond_to?(:downcase) ? val.downcase : val.to_s)
end
+
+ private
+ def when_org_changes
+ if org_id != org_id_was
+ unless can_change_org?
+ perms.delete_all
+ remove_token!
+ end
+ end
+ end
end
diff --git a/app/views/answers/_new_edit.html.erb b/app/views/answers/_new_edit.html.erb
index caccfc1..ca97561 100644
--- a/app/views/answers/_new_edit.html.erb
+++ b/app/views/answers/_new_edit.html.erb
@@ -2,14 +2,59 @@
+
+