diff --git a/app/controllers/org_admin/templates_controller.rb b/app/controllers/org_admin/templates_controller.rb new file mode 100644 index 0000000..bed28f0 --- /dev/null +++ b/app/controllers/org_admin/templates_controller.rb @@ -0,0 +1,475 @@ +module OrgAdmin + class TemplatesController < ApplicationController + include Paginable + after_action :verify_authorized + + # GET /org_admin/templates + # ----------------------------------------------------- + def index + authorize Template + valid_orgs = current_user.can_super_admin? ? Org.not_funder : Org.find(current_user.org) + org_templates = Template.get_latest_template_versions(valid_orgs).page(1) + funder_templates = Template.get_latest_template_versions(Org.funder).page(1) + + # If the user is an Org Admin look for customizations to funder templates + customizations = {} + unless current_user.can_super_admin? + funder_templates.each do |funder_template| + customization = Template.org_customizations(funder_template.dmptemplate_id, current_user.org_id) + customizations[customization.dmptemplate_id] = customization if customization.present? + end + end + + # Gather up all of the publication dates for the live versions of each template. + published = {} + [funder_templates, org_templates].each do |collection| + collection.each do |template| + live = Template.live(template.dmptemplate_id) + published[template.dmptemplate_id] = live.updated_at if live.present? + end + end + + render 'index', locals: { + funder_templates: funder_templates, + org_templates: org_templates, + customized_templates: customizations, + published: published, + current_org: current_user.org, + orgs: Org.all + } + end + + # GET /org_admin/templates/new + # ----------------------------------------------------- + def new + authorize Template + end + + # POST /org_admin/templates + # ----------------------------------------------------- + def create + authorize Template + # creates a new template with version 0 and new dmptemplate_id + @template = Template.new(params[:template]) + @template.org_id = current_user.org.id + @template.description = params['template-desc'] + + if @template.save + redirect_to edit_org_admin_template_path(@template), notice: success_message(_('template'), _('created')) + else + @hash = @template.to_hash + flash[:alert] = failed_create_error(@template, _('template')) + render action: "new" + end + end + + # GET /org_admin/templates/:id/edit + # ----------------------------------------------------- + def edit + @template = Template.includes(:org, phases: [sections: [questions: [:question_options, :question_format, :annotations]]]).find(params[:id]) + authorize @template + + @current = Template.current(@template.dmptemplate_id) + + if @template == @current + # If the template is published + if @template.published? + # We need to create a new, editable version + new_version = Template.deep_copy(@template) + new_version.version = (@template.version + 1) + new_version.published = false + new_version.save + @template = new_version + # @current = Template.current(@template.dmptemplate_id) + end + else + flash[:notice] = _('You are viewing a historical version of this template. You will not be able to make changes.') + end + + # If the template is published + if @template.published? + # We need to create a new, editable version + new_version = Template.deep_copy(@template) + new_version.version = (@template.version + 1) + new_version.published = false + new_version.save + @template = new_version + end + + # once the correct template has been generated, we convert it to hash + @template_hash = @template.to_hash + render('container', + locals: { + partial_path: 'edit', + template: @template, + current: @current, + template_hash: @template_hash + }) + end + + # PUT /org_admin/templates/:id + # ----------------------------------------------------- + def update + @template = Template.find(params[:id]) + authorize @template + + current = Template.current(@template.dmptemplate_id) + + # Only allow the current version to be updated + if current != @template + redirect_to edit_org_admin_template_path(@template), notice: _('You can not edit a historical version of this template.') + + else + if @template.description != params["template-desc"] || + @template.title != params[:template][:title] + @template.dirty = true + end + + @template.description = params["template-desc"] + @template.links = JSON.parse(params["template-links"]) if params["template-links"].present? + + # If the visibility checkbox is not checked and the user's org is a funder set the visibility to public + # otherwise default it to organisationally_visible + if current_user.org.funder? && params[:template_visibility].nil? + @template.visibility = Template.visibilities[:publicly_visible] + else + @template.visibility = Template.visibilities[:organisationally_visible] + end + + if @template.update_attributes(params[:template]) + flash[:notice] = success_message(_('template'), _('saved')) + + else + flash[:alert] = failed_update_error(@template, _('template')) + end + + redirect_to action: 'edit', id: params[:id] + end + end + + # DELETE /org_admin/templates/:id + # ----------------------------------------------------- + def destroy + @template = Template.find(params[:id]) + authorize @template + + if @template.plans.length <= 0 + current = Template.current(@template.dmptemplate_id) + + # Only allow the current version to be destroyed + if current == @template + if @template.destroy + flash[:notice] = success_message(_('template'), _('removed')) + redirect_to org_admin_templates_path + else + @hash = @template.to_hash + flash[:alert] = failed_destroy_error(@template, _('template')) + render org_admin_templates_path + end + else + flash[:alert] = _('You cannot delete historical versions of this template.') + redirect_to org_admin_templates_path + end + else + flash[:alert] = _('You cannot delete a template that has been used to create plans.') + redirect_to org_admin_templates_path + end + end + + # GET /org_admin/templates/:id/history + # ----------------------------------------------------- + def history + @template = Template.find(params[:id]) + authorize @template + @templates = Template.where(dmptemplate_id: @template.dmptemplate_id).order(:version) + @current = Template.current(@template.dmptemplate_id) + end + + # GET /org_admin/templates/:id/customize + # ----------------------------------------------------- + def customize + @template = Template.find(params[:id]) + authorize @template + + customisation = Template.deep_copy(@template) + customisation.org = current_user.org + customisation.version = 0 + customisation.customization_of = @template.dmptemplate_id + customisation.dmptemplate_id = loop do + random = rand 2147483647 + break random unless Template.exists?(dmptemplate_id: random) + end + customisation.dirty = true + customisation.save + + customisation.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 + + redirect_to edit_org_admin_template_path(customisation) + end + + # GET /org_admin/templates/:id/transfer_customization + # the funder template's id is passed through here + # ----------------------------------------------------- + def 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.where(org_id: current_user.org_id).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 edit_org_admin_template_path(new_customization) + end + + + # GET /org_admin/templates/funders/:page (AJAX) + # ----------------------------------------------------- + def funders + authorize Template + if params[:page] == 'ALL' + templates = Template.get_latest_template_versions(Org.funder) + else + templates = Template.get_latest_template_versions(Org.funder).page(params[:page]) + end + # Include the default template in the list of funder templates + templates << Template.default + + # If the user is an Org Admin look for customizations to funder templates + customizations = [] + unless current_user.can_super_admin? + templates.each do |funder_template| + customization = Template.org_customizations(funder_template.id, current_user.org_id) + customizations << customization if customization.present? + end + end + + # Gather up all of the publication dates for the live versions of each template. + published = {} + templates.each do |template| + live = Template.live(template.dmptemplate_id) + published[template.dmptemplate_id] = live.updated_at if live.present? + end + + paginable_renderise(partial: 'funder_templates_list', scope: templates, + locals: {current_org: current_user.org.id, customizations: customizations, published: published}) + end + + # GET /org_admin/templates/orgs/:page (AJAX) + # ----------------------------------------------------- + def orgs + authorize Template + valid_orgs = current_user.can_super_admin? ? Org.not_funder : Org.find(current_user.org) + if params[:page] == 'ALL' + templates = Template.get_latest_template_versions(valid_orgs) + else + templates = Template.get_latest_template_versions(valid_orgs).page(params[:page]) + end + + # Gather up all of the publication dates for the live versions of each template. + published = {} + templates.each do |template| + live = Template.live(template.dmptemplate_id) + published[template.dmptemplate_id] = live.updated_at if live.present? + end + + paginable_renderise(partial: 'templates_list', scope: templates, locals: {current_org: current_user.org.id, published: published}) + end + + # PUT /org_admin/templates/:id/copy (AJAX) + # ----------------------------------------------------- + def copy + @template = Template.find(params[:id]) + authorize @template + + new_copy = Template.deep_copy(@template) + new_copy.title = "Copy of " + @template.title + new_copy.version = 0 + new_copy.published = false + new_copy.dmptemplate_id = loop do + random = rand 2147483647 + break random unless Template.exists?(dmptemplate_id: random) + end + + if new_copy.save + flash[:notice] = 'Template was successfully copied.' + redirect_to edit_org_admin_template_path(id: new_copy.id, edit: true), notice: _('Information was successfully created.') + else + flash[:alert] = failed_create_error(new_copy, _('template')) + end + + end + + # PUT /org_admin/templates/:id/publish (AJAX) + # ----------------------------------------------------- + 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.') + + else + # Unpublish the older published version if there is one + live = Template.live(@template.dmptemplate_id) + if !live.nil? and self != live + live.published = false + live.save! + end + # Set the dirty flag to false + @template.dirty = false + @template.published = true + @template.save + + flash[:notice] = _('Your template has been published and is now available to users.') + + redirect_to org_admin_templates_path + end + end + + # PUT /org_admin/templates/:id/unpublish (AJAX) + # ----------------------------------------------------- + def unpublish + template = Template.find(params[:id]) + authorize template + + # Unpublish the live version + @template = Template.live(template.dmptemplate_id) + + if @template.nil? + flash[:alert] = _('That template 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') + end + + redirect_to org_admin_templates_path + end + + # PUT /org_admin/template_options (AJAX) + # Collect all of the templates available for the org+funder combination + # -------------------------------------------------------------------------- + def template_options() + org_id = (plan_params[:org_id] == '-1' ? '' : plan_params[:org_id]) + funder_id = (plan_params[:funder_id] == '-1' ? '' : plan_params[:funder_id]) + authorize Template.new + + templates = [] + + if org_id.present? || funder_id.present? + if funder_id.blank? + # Load the org's template(s) + if org_id.present? + org = Org.find(org_id) + templates = Template.valid.where(published: true, org: org, customization_of: nil).to_a + end + + else + funder = Org.find(funder_id) + # Load the funder's template(s) + templates = Template.valid.where(published: true, org: funder).to_a + + if org_id.present? + org = Org.find(org_id) + + # Swap out any organisational cusotmizations of a funder template + templates.each do |tmplt| + customization = Template.valid.find_by(published: true, org: org, customization_of: tmplt.dmptemplate_id) + if customization.present? && tmplt.updated_at < customization.created_at + templates.delete(tmplt) + templates << customization + end + end + end + end + end + + # If no templates were available use the generic templates + if templates.empty? + templates << Template.where(is_default: true, published: true).first + end + templates = (templates.count > 0 ? templates.sort{|x,y| x.title <=> y.title} : []) + + render json: {"templates": templates.collect{|t| {id: t.id, title: t.title} }}.to_json + end + + + # ====================================================== + private + def plan_params + params.require(:plan).permit(:org_id, :funder_id) + end + end +end \ No newline at end of file diff --git a/app/controllers/phases_controller.rb b/app/controllers/phases_controller.rb index 18e58f6..b93ac76 100644 --- a/app/controllers/phases_controller.rb +++ b/app/controllers/phases_controller.rb @@ -106,7 +106,7 @@ else @original_org = @phase.template.org end - render('/templates/container', + render('/org_admin/templates/container', locals: { partial_path: 'admin_show', phase: @phase, @@ -132,7 +132,7 @@ @phase.template = @template authorize @phase @phase.number = @template.phases.count + 1 - render('/templates/container', + render('/org_admin/templates/container', locals: { partial_path: 'admin_add', template: @template @@ -155,7 +155,7 @@ else flash[:alert] = failed_create_error(@phase, _('phase')) @template = @phase.template - redirect_to admin_template_template_path(id: @phase.template_id) + redirect_to edit_org_admin_template_path(id: @phase.template_id) end end @@ -198,7 +198,7 @@ @template.dirty = true @template.save! - redirect_to admin_template_template_path(@template), notice: success_message(_('phase'), _('deleted')) + redirect_to edit_org_admin_template_path(@template), notice: success_message(_('phase'), _('deleted')) else @sections = @phase.sections diff --git a/app/controllers/plans_controller.rb b/app/controllers/plans_controller.rb index 89c03ae..3bae0a0 100644 --- a/app/controllers/plans_controller.rb +++ b/app/controllers/plans_controller.rb @@ -18,8 +18,8 @@ authorize @plan # Get all of the available funders and non-funder orgs - @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 } + @funders = Org.funder.joins(:templates).where(templates: {published: true}).uniq.sort{|x,y| x.name <=> y.name } + @orgs = (Org.institution + Org.managing_orgs).flatten.uniq.sort{|x,y| x.name <=> y.name } # Get the current user's org @default_org = current_user.org if @orgs.include?(current_user.org) diff --git a/app/controllers/public_pages_controller.rb b/app/controllers/public_pages_controller.rb index cdf5041..fe8c78a 100644 --- a/app/controllers/public_pages_controller.rb +++ b/app/controllers/public_pages_controller.rb @@ -4,7 +4,7 @@ # GET template_index # ----------------------------------------------------- def template_index - template_ids = Template.where(org_id: Org.funders.pluck(:id), visibility: Template.visibilities[:publicly_visible]).valid.pluck(:dmptemplate_id).uniq << Template.where(is_default: true, published: true).pluck(:dmptemplate_id) + template_ids = Template.where(org_id: Org.funder.pluck(:id), visibility: Template.visibilities[:publicly_visible]).valid.pluck(:dmptemplate_id).uniq << Template.where(is_default: true, published: true).pluck(:dmptemplate_id) @templates = [] template_ids.flatten.each do |tid| t = Template.live(tid) diff --git a/app/controllers/templates_controller.rb b/app/controllers/templates_controller.rb deleted file mode 100644 index 0fdb404..0000000 --- a/app/controllers/templates_controller.rb +++ /dev/null @@ -1,431 +0,0 @@ -# [+Project:+] DMPRoadmap -# [+Description:+] This controller is responsible for all the actions in the admin interface under templates (e.g. phases, versions, sections, questions, suggested answer) (index; show; create; edit; delete) -# [+Copyright:+] Digital Curation Centre and University of California Curation Center - -class TemplatesController < ApplicationController - #respond_to :html - after_action :verify_authorized - helper TemplateHelper - # GET /org/admin/templates/:id/admin_index - # ----------------------------------------------------- - def admin_index - authorize Template - - funder_templates, org_templates, organisation_templates = [], [], [] - - # Get all of the unique template family ids (dmptemplate_id) for each funder and the current org - funder_ids = Template.valid_published().joins(:org).where(Org.funder_condition).pluck(:dmptemplate_id) - org_ids = current_user.org.templates.where(customization_of: nil).valid.collect{|t| t.dmptemplate_id }.flatten.uniq - organisation_ids = Template.valid_published(is_default: true).joins(:org) - .where(Org.organisation_condition).where(["org_id <> ?", current_user.org_id]).pluck(:dmptemplate_id) - - org_ids.each do |id| - current = Template.current(id) - live = Template.live(id) - org_templates << {current: current, live: live} - end - funder_ids.each do |id| - 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 - - organisation_ids.each do |id| - organisation_live = Template.live(id) - current = Template.org_customizations(id, current_user.org_id) - live = current.present? ? Template.live(current.dmptemplate_id) : nil - current = organisation_live unless current.present? - organisation_templates << { current: current, live: live, organisation_live: organisation_live, stale: organisation_live.updated_at > current.created_at } - end - - @funder_templates = funder_templates.sort{|x,y| - x[:current].title <=> y[:current].title - } - @org_templates = org_templates.sort{|x,y| - x[:current].title <=> y[:current].title - } - @organisation_templates = organisation_templates.sort{|x,y| - x[:current].title <=> y[:current].title - } - end - - # GET /org/admin/templates/:id/admin_customize - # ----------------------------------------------------- - def admin_customize - @template = Template.find(params[:id]) - authorize @template - - customisation = Template.deep_copy(@template) - customisation.org = current_user.org - customisation.version = 0 - customisation.customization_of = @template.dmptemplate_id - customisation.dmptemplate_id = loop do - random = rand 2147483647 - break random unless Template.exists?(dmptemplate_id: random) - end - customisation.dirty = true - customisation.save - - customisation.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 - - 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.where(org_id: current_user.org_id).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 - @template = Template.find(params[:id]) - authorize @template - - current = Template.current(@template.dmptemplate_id) - - # Only allow the current version to be updated - if current != @template - redirect_to admin_template_template_path(@template), alert: _('You can not publish a historical version of this template.') - - else - # Unpublish the older published version if there is one - live = Template.live(@template.dmptemplate_id) - if !live.nil? and self != live - live.published = false - live.save! - end - # Set the dirty flag to false - @template.dirty = false - @template.published = true - @template.save - - flash[:notice] = _('Your template has been published and is now available to users.') - - redirect_to admin_index_template_path(current_user.org) - end - end - - # PUT /org/admin/templates/:id/admin_unpublish - # ----------------------------------------------------- - def admin_unpublish - template = Template.find(params[:id]) - authorize template - - # Unpublish the live version - @template = Template.live(template.dmptemplate_id) - - if @template.nil? - flash[:alert] = _('That template 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') - end - - redirect_to admin_index_template_path(current_user.org) - end - - # GET /org/admin/templates/:id/admin_template - # ----------------------------------------------------- - def admin_template - @template = Template.includes(:org, phases: [sections: [questions: [:question_options, :question_format, :annotations]]]).find(params[:id]) - authorize @template - - @current = Template.current(@template.dmptemplate_id) - - if @template == @current - # If the template is published - if @template.published? - # We need to create a new, editable version - new_version = Template.deep_copy(@template) - new_version.version = (@template.version + 1) - new_version.published = false - new_version.save - @template = new_version -# @current = Template.current(@template.dmptemplate_id) - end - else - flash[:notice] = _('You are viewing a historical version of this template. You will not be able to make changes.') - end - - # If the template is published - if @template.published? - # We need to create a new, editable version - new_version = Template.deep_copy(@template) - new_version.version = (@template.version + 1) - new_version.published = false - new_version.save - @template = new_version - end - - # once the correct template has been generated, we convert it to hash - @template_hash = @template.to_hash - render('container', - locals: { - partial_path: 'admin_template', - template: @template, - current: @current, - template_hash: @template_hash - }) - end - - - # PUT /org/admin/templates/:id/admin_update - # ----------------------------------------------------- - def admin_update - @template = Template.find(params[:id]) - authorize @template - - current = Template.current(@template.dmptemplate_id) - - # Only allow the current version to be updated - if current != @template - redirect_to admin_template_template_path(@template), notice: _('You can not edit a historical version of this template.') - - else - if @template.description != params["template-desc"] || - @template.title != params[:template][:title] - @template.dirty = true - end - - @template.description = params["template-desc"] - @template.links = JSON.parse(params["template-links"]) if params["template-links"].present? - - # If the visibility checkbox is not checked and the user's org is a funder set the visibility to public - # otherwise default it to organisationally_visible - if current_user.org.funder? && params[:template_visibility].nil? - @template.visibility = Template.visibilities[:publicly_visible] - else - @template.visibility = Template.visibilities[:organisationally_visible] - end - - if @template.update_attributes(params[:template]) - flash[:notice] = success_message(_('template'), _('saved')) - - else - flash[:alert] = failed_update_error(@template, _('template')) - end - - redirect_to action: 'admin_template', id: params[:id] - end - end - - - # GET /org/admin/templates/:id/admin_new - # ----------------------------------------------------- - def admin_new - authorize Template - end - - - # POST /org/admin/templates/:id/admin_create - # ----------------------------------------------------- - def admin_create - # creates a new template with version 0 and new dmptemplate_id - @template = Template.new(params[:template]) - authorize @template - @template.org_id = current_user.org.id - @template.description = params['template-desc'] - - if @template.save - redirect_to admin_template_template_path(@template), notice: success_message(_('template'), _('created')) - else - @hash = @template.to_hash - flash[:alert] = failed_create_error(@template, _('template')) - render action: "admin_new" - end - end - - - # DELETE /org/admin/templates/:id/admin_destroy - # ----------------------------------------------------- - def admin_destroy - @template = Template.find(params[:id]) - authorize @template - - current = Template.current(@template.dmptemplate_id) - - # Only allow the current version to be destroyed - if current == @template - if @template.destroy - redirect_to admin_index_template_path - else - @hash = @template.to_hash - flash[:notice] = failed_destroy_error(@template, _('template')) - render admin_template_template_path(@template) - end - else - flash[:alert] = _('You cannot delete historical versions of this template.') - redirect_to admin_index_template_path - end - end - - # GET /org/admin/templates/:id/admin_template_history - # ----------------------------------------------------- - def admin_template_history - @template = Template.find(params[:id]) - authorize @template - @templates = Template.where(dmptemplate_id: @template.dmptemplate_id).order(:version) - @current = Template.current(@template.dmptemplate_id) - end - - # PUT /org/admin/templates/:id/admin_copy - # ----------------------------------------------------- - def admin_copy - @template = Template.find(params[:id]) - authorize @template - - new_copy = Template.deep_copy(@template) - new_copy.title = "Copy of " + @template.title - new_copy.version = 0 - new_copy.published = false - new_copy.dmptemplate_id = loop do - random = rand 2147483647 - break random unless Template.exists?(dmptemplate_id: random) - end - - if new_copy.save - flash[:notice] = 'Template was successfully copied.' - redirect_to admin_template_template_path(id: new_copy.id, edit: true), notice: _('Information was successfully created.') - else - flash[:alert] = failed_create_error(new_copy, _('template')) - end - - end - - # Collect all of the templates available for the org+funder combination - # -------------------------------------------------------------------------- - def template_options() - org_id = (plan_params[:org_id] == '-1' ? '' : plan_params[:org_id]) - funder_id = (plan_params[:funder_id] == '-1' ? '' : plan_params[:funder_id]) - authorize Template.new - - templates = [] - - if org_id.present? || funder_id.present? - if funder_id.blank? - # Load the org's template(s) - if org_id.present? - org = Org.find(org_id) - templates = Template.valid.where(published: true, org: org, customization_of: nil).to_a - end - - else - funder = Org.find(funder_id) - # Load the funder's template(s) - templates = Template.valid.where(published: true, org: funder).to_a - - if org_id.present? - org = Org.find(org_id) - - # Swap out any organisational cusotmizations of a funder template - templates.each do |tmplt| - customization = Template.valid.find_by(published: true, org: org, customization_of: tmplt.dmptemplate_id) - if customization.present? && tmplt.updated_at < customization.created_at - templates.delete(tmplt) - templates << customization - end - end - end - end - end - - # If no templates were available use the generic templates - if templates.empty? - templates << Template.where(is_default: true, published: true).first - end - templates = (templates.count > 0 ? templates.sort{|x,y| x.title <=> y.title} : []) - - render json: {"templates": templates.collect{|t| {id: t.id, title: t.title} }}.to_json - end - - private - def plan_params - params.require(:plan).permit(:org_id, :funder_id) - end - -end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 51d9e30..996a33d 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -78,8 +78,33 @@ redirect_to "#{edit_user_registration_path}\#notification-preferences", notice: success_message(_('preferences'), _('saved')) end + # PUT /users/:id/org_swap (AJAX) + # ----------------------------------------------------- + def org_swap + # Allows the user to swap their org affiliation on the fly + authorize current_user + org = Org.find(org_swap_params[:org_id]) + if org.present? + current_user.org = org + if current_user.save! + render json: { + msg: _('Your organisation affiliation has been changed. You may now edit templates for %{org_name}.') % {org_name: current_user.org.name} + }.to_json + else + render json: { + err: _('Unable to change your organisation affiliation at this time.') + }.to_json + end + else + render json: {}.to_json + end + end + private - + def org_swap_params + params.require(:user).permit(:org_id, :org_name) + end + ## # html forms return our boolean values as strings, this converts them to true/false def booleanize_hash(node) diff --git a/app/models/guidance.rb b/app/models/guidance.rb index ca9ab48..24c1cc0 100644 --- a/app/models/guidance.rb +++ b/app/models/guidance.rb @@ -98,7 +98,7 @@ end # guidance groups are viewable if they are owned by a funder - if Org.funders.include?(guidance.guidance_group.org) + if Org.funder.include?(guidance.guidance_group.org) viewable = true end end @@ -119,7 +119,7 @@ def self.all_viewable(user) managing_groups = Org.includes(guidance_groups: :guidances).managing_orgs.collect{|o| o.guidance_groups} # find all groups owned by a Funder organisation - funder_groups = Org.includes(guidance_groups: :guidances).funders.collect{|org| org.guidance_groups} + funder_groups = Org.includes(guidance_groups: :guidances).funder.collect{|org| org.guidance_groups} # find all groups owned by any of the user's organisations organisation_groups = user.org.guidance_groups diff --git a/app/models/guidance_group.rb b/app/models/guidance_group.rb index c4bc700..8974a37 100644 --- a/app/models/guidance_group.rb +++ b/app/models/guidance_group.rb @@ -106,7 +106,7 @@ managing_org_groups = Org.includes(guidance_groups: [guidances: :themes]).managing_orgs.collect{|org| org.guidance_groups} # find all groups owned by a Funder organisation - funder_groups = Org.includes(:guidance_groups).funders.collect{|org| org.guidance_groups} + funder_groups = Org.includes(:guidance_groups).funder.collect{|org| org.guidance_groups} organisation_groups = [user.org.guidance_groups] diff --git a/app/models/org.rb b/app/models/org.rb index df88458..a9f0e3c 100644 --- a/app/models/org.rb +++ b/app/models/org.rb @@ -60,9 +60,6 @@ # Predefined queries for retrieving the managain organisation and funders scope :managing_orgs, -> { where(abbreviation: Rails.configuration.branding[:organisation][:abbreviation]) } - scope :funders, -> { where(org_type: 2) } - scope :institutions, -> { where(org_type: 1) } - # EVALUATE CLASS AND INSTANCE METHODS BELOW # diff --git a/app/models/template.rb b/app/models/template.rb index 65a10ea..d0d076b 100644 --- a/app/models/template.rb +++ b/app/models/template.rb @@ -80,6 +80,22 @@ Template.where(customization_of: dmptemplate_id, org_id: org_id).order(version: :desc).valid.first end + def self.get_latest_template_versions(orgs) + # get the unique dmptemplate_ids (template version families) + families = Template.valid.where(org: orgs, customization_of: nil).pluck(:dmptemplate_id) + + # return the most current versions of each template version family + id_query = "SELECT templates.dmptemplate_id, templates.id, current.version "\ + "FROM "\ + "(SELECT MAX(version) AS version, dmptemplate_id "\ + "FROM templates WHERE dmptemplate_id in (#{families.join(', ')}) "\ + "GROUP BY dmptemplate_id) as current "\ + "INNER JOIN templates ON current.version = templates.version AND current.dmptemplate_id = templates.dmptemplate_id;" + + ids = Template.find_by_sql(id_query).collect{|t| t.id } + Template.includes(:org).where(id: ids).order('orgs.name, templates.title') + end + ## # deep copy the given template and all of it's associations # diff --git a/app/policies/template_policy.rb b/app/policies/template_policy.rb index 157e9c3..64cf610 100644 --- a/app/policies/template_policy.rb +++ b/app/policies/template_policy.rb @@ -1,11 +1,67 @@ class TemplatePolicy < ApplicationPolicy attr_reader :user, :template - - def initialize(user, template) - raise Pundit::NotAuthorizedError, "must be logged in" unless user + + def initialize(user, template = Template.new) + raise Pundit::NotAuthorizedError, _("must be logged in") unless user.is_a?(User) @user = user @template = template end + + def index? + user.can_super_admin? || user.can_modify_templates? + end + + def new? + user.can_super_admin? || user.can_modify_templates? + end + + def create? + user.can_super_admin? || user.can_modify_templates? + end + + def edit? + user.can_super_admin? || (user.can_modify_templates? && template.org_id == user.org_id) + end + + def update? + user.can_super_admin? || (user.can_modify_templates? && template.org_id == user.org_id) + end + + def destroy? + user.can_super_admin? || (user.can_modify_templates? && (template.org_id == user.org_id)) + end + + def history? + user.can_super_admin? || (user.can_modify_templates? && template.org_id == user.org_id) + end + + def customize? + user.can_super_admin? || user.can_modify_templates? + end + + def transfer_customization? + user.can_super_admin? || user.can_modify_templates? + end + + # Pagination + def funders? + user.can_super_admin? || user.can_modify_templates? + end + def orgs? + user.can_super_admin? || user.can_modify_templates? + end + + # AJAX Calls + def copy? + user.can_super_admin? || (user.can_modify_templates? && (template.org_id == user.org_id)) + end + def publish? + user.can_super_admin? || (user.can_modify_templates? && (template.org_id == user.org_id)) + end + def unpublish? + user.can_super_admin? || (user.can_modify_templates? && (template.org_id == user.org_id)) + end + ## # Users can modify templates if: @@ -13,64 +69,13 @@ # - The template which they are modifying belongs to their org ## - def admin_index? - user.can_modify_templates? - end - def admin_template? - user.can_modify_templates? && (template.org_id == user.org_id) - end - def admin_customize? - user.can_modify_templates? - end - - def admin_publish? - user.can_modify_templates? && (template.org_id == user.org_id) - end - - def admin_unpublish? - user.can_modify_templates? && (template.org_id == user.org_id) - end - - def admin_update? - user.can_modify_templates? && (template.org_id == user.org_id) - end - - def admin_new? - user.can_modify_templates? - end - - def admin_create? - user.can_modify_templates? && (template.org_id.nil? || (template.org_id == user.org_id)) - end - - def admin_destroy? - user.can_modify_templates? && (template.org_id == user.org_id) - end - - def admin_template_history? - user.can_modify_templates? && (template.org_id == user.org_id) - end - - def admin_transfer_customization? - user.can_modify_templates? - end - - def admin_copy? - user.can_modify_templates? && (template.org_id == user.org_id) - end - # Anyone with an account should be able to get templates for the sepecified research_org + funder # This policy is applicable to the Create Plan page def template_options? user.present? end - class Scope < Scope - def resolve - scope.where(org_id: user.org_id) - end - end -end +end \ No newline at end of file diff --git a/app/policies/user_policy.rb b/app/policies/user_policy.rb index a97a91b..abe3184 100644 --- a/app/policies/user_policy.rb +++ b/app/policies/user_policy.rb @@ -19,6 +19,11 @@ @user.can_grant_permissions? && (@users.org_id == @user.org_id) end + # Allows the user to swap their org affiliation on the fly + def org_swap? + user.can_super_admin? + end + class Scope < Scope def resolve scope.where(org_id: user.org_id) diff --git a/app/views/layouts/_branding.html.erb b/app/views/layouts/_branding.html.erb index 6705e94..9e5ddd3 100644 --- a/app/views/layouts/_branding.html.erb +++ b/app/views/layouts/_branding.html.erb @@ -35,68 +35,52 @@ <% end %> <% end %> - - diff --git a/app/views/org_admin/templates/_admin_nav_tabs.html.erb b/app/views/org_admin/templates/_admin_nav_tabs.html.erb new file mode 100644 index 0000000..70dd9d1 --- /dev/null +++ b/app/views/org_admin/templates/_admin_nav_tabs.html.erb @@ -0,0 +1,17 @@ + diff --git a/app/views/org_admin/templates/_edit.html.erb b/app/views/org_admin/templates/_edit.html.erb new file mode 100644 index 0000000..bb4b6a7 --- /dev/null +++ b/app/views/org_admin/templates/_edit.html.erb @@ -0,0 +1,44 @@ +
+
+ <% if template == current && template.customization_of.nil? %> + + <% end %> +
+
+
+
+
+ <%= render partial: "org_admin/templates/show_template", locals: { template: template, current: current, template_hash: template_hash }%> +
+
+
+ +
+
+
+ + <% if template_hash[:template][:phases].present? %> + <% template_hash[:template][:phases].each do |phase_no, phase_hash| %> + <% phase = phase_hash[:data] %> +
+ +
" class="panel-collapse collapse" role="tabpanel" aria-labelledby="<%= "headingPhase#{phase.id}" %>"> +
+ <%= render partial: 'org_admin/templates/show_phases_sections', locals: { phase: phase, phase_hash: phase_hash, template: template, current: current } %> +
+
+
+ <% end %> + <% end %> +
+
+
diff --git a/app/views/org_admin/templates/_edit_template.html.erb b/app/views/org_admin/templates/_edit_template.html.erb new file mode 100644 index 0000000..b64f5c4 --- /dev/null +++ b/app/views/org_admin/templates/_edit_template.html.erb @@ -0,0 +1,76 @@ + +<%= form_for(template, url: org_admin_template_path(template), html: { method: :put }) do |f| %> +
+ <%= f.label(:title, _('Title'), class: "control-label") %> + <%= f.text_field(:title, class: "form-control", "aria-required": false, 'data-toggle': 'tooltip', title: _('Please enter a title for your template.')) %> +
+ +
+ <%= f.label(:description, _('Description'), class: "control-label") %> +
+ <%= text_area_tag("template-desc", template.description, { class: 'template', "aria-required": false }) %> +
+
+ +
+ <%= f.label _('Visibility'), class: 'control-label' %> +
+ <%= f.label(:visibility, + raw("#{check_box_tag('template_visibility', '0', (template.visibility == 'organisationally_visible'))} #{_('for internal %{org_name} use only') % {org_name: @template.org.name}}")) %> +
+
+ +
+ <%= label_tag(:status, _('Status'), class: "control-label") %> +

+ <% if template_hash[:live].nil? %> + <%= _('Unpublished') %> + <% elsif template_hash[:current].dirty? %> + <%= _('You have un-published changes') %> + <% else %> + <%= _('Published') %> + <% end %> +

+
+ +
+ <%= label_tag(:created_at, _('Created at'), class: "control-label") %> +

+ <%= l template.created_at.to_date, formats: :short %> +

+
+ +
+ <%= label_tag(:updated, _('Last updated'), class: "control-label") %> +

+ <%= l template.updated_at.to_date, formats: :short %> +

+
+ + <% if template.org.funder? %> +
+ <%= render(partial: '/shared/links', + locals: { + context: 'funder', + title: _('Funder Links'), + links: template.links['funder'], + max_number_links: MAX_NUMBER_LINKS_FUNDER, + tooltip: _('Add links to funder websites that provide additional information about the requirements for this template') }) %> +
+
+ <%= render(partial: '/shared/links', + locals: { + context: 'sample_plan', + title: _('Sample Plan Links'), + links: template.links['sample_plan'], + max_number_links: MAX_NUMBER_LINKS_SAMPLE_PLAN, + tooltip: _('Add links to sample plans if provided by the funder.') }) %> +
+ <%= hidden_field_tag('template-links', value: template.links) %> + <% end %> + +
+ <%= f.button(_('Save'), class: 'btn btn-default', type: "submit") %> + <%= link_to(_('Cancel'), '#', { class: 'btn btn-default template_show_link', role: "button" }) %> +
+<% end %> \ No newline at end of file diff --git a/app/views/org_admin/templates/_funder_templates_list.html.erb b/app/views/org_admin/templates/_funder_templates_list.html.erb new file mode 100644 index 0000000..d584090 --- /dev/null +++ b/app/views/org_admin/templates/_funder_templates_list.html.erb @@ -0,0 +1,114 @@ +<% # locals: templates, current_org %> + +
+ + + <% if scope.length > TABLE_FILTER_MIN_ROWS %> + + + + <% end %> + + + + + + + + + + <% scope.each do |template| %> + <% customization = customizations[template.dmptemplate_id] %> + + + + + + + + <% end %> + +
+ <%= render(partial: "shared/table_filter", locals: { placeholder: _('Search')}) %> +
<%= _('Template Name') %><%= _('Funder') %><%= _('Status') %><%= _('Edited Date') %>
+ <%= template.title %> + + <%= raw template.org.name %> + + <% if current_user.can_super_admin? %> + <% if !published[template.dmptemplate_id].present? %> + <%= _('Unpublished') %> + <% elsif template.dirty? %> + <%= _('Unpublished changes') %> + <% else %> + <%= _('Published') %> + <% end %> + <% else %> + <% if customization.present? %> + + <% if customization.updated_at < template.updated_at %> + <%= _('Original funder template has changed!')%> + <% elsif !template.published? %> + + <%= b_label = _('Funder version is un-published') %> + <% elsif customization.dirty? %> + <%= _('You have un-published changes') %> + <% else %> + <%= _('Published') %> + <% end %> + <% else %> + <%= _('Not Customised') %> + <% end %> + <% end %> + + <% last_temp_updated = template.updated_at %> + <%= l last_temp_updated.to_date, formats: :short %> + + +
+
\ No newline at end of file diff --git a/app/views/org_admin/templates/_show_phases_sections.html.erb b/app/views/org_admin/templates/_show_phases_sections.html.erb new file mode 100644 index 0000000..e1ab1ad --- /dev/null +++ b/app/views/org_admin/templates/_show_phases_sections.html.erb @@ -0,0 +1,57 @@ + +
+
+

+ <%= raw phase.description %> +

+
+
+
+
+
+ <% phase_button_text = template.customization_of.nil? ? _('Show Phase') : _('Customize Phase') %> + <%= link_to phase_button_text, admin_show_phase_path(id: phase.id), { class: "btn btn-default", role: 'button' } %> + <% if template == current && phase.modifiable %> + <%= link_to _('Delete'), admin_destroy_phase_path(phase_id: phase.id), { + confirm: _("You are about to delete '%{phase_title}'. This will affect versions, sections and questions linked to this phase. Are you sure?") % { phase_title: phase.title }, + method: :delete, + class: "btn btn-default", role: "button" } + %> + <% end %> +
+
+
+
+
+ <% if phase_hash[:sections].length > 0 %> +
+ + + + + + + + + <% (phase_hash[:sections].values.sort_by { |key| key[:data][:number] }).each do |section| %> + + + + + <% end %> + +
<%= _('Sections')%><%= _('Questions')%>
+

<%= section[:data].title %>

+
+ <% if section[:questions].present? %> +
    + <% (section[:questions].values.sort_by { |key| key[:data][:number] }).each do |question| %> +
  • <%= raw question[:data].text %>
  • + <% end %> +
+ <% end %> +
+
+ <% end %> +
+
diff --git a/app/views/org_admin/templates/_show_template.html.erb b/app/views/org_admin/templates/_show_template.html.erb new file mode 100644 index 0000000..f61514b --- /dev/null +++ b/app/views/org_admin/templates/_show_template.html.erb @@ -0,0 +1,35 @@ + +
+
<%= _('Title') %>
+
<%= template.title %>
+
<%= _('Description') %>
+
+ <%= (!template.description.nil? && template.description != "" ? raw( template.description) : '-') %> +
+
<%= _('Status') %>
+
+ <% if template_hash[:live].nil? %> + <%= _('Unpublished') %> + + <% elsif template_hash[:current].dirty? %> + <%= _('You have un-published changes') %> + + <% else %> + <%= _('Published') %> + <% end %> +
+ <% if template.org.funder? %> +
<%= _('Visibility') %>
+
<%= (template.visibility == 'organisationally_visible' ? _('for internal %{org_name} use only') % {org_name: @template.org.name} : _('available to the public') + (template_hash[:live].nil? ? ' (once published)' : '')) %>
+ <% end %> +
<%= _('Created at') %>
+
<%= l template.created_at.to_date, formats: :short %>
+
<%= _('Last updated') %>
+
<%= l template.updated_at.to_date, formats: :short %>
+
+ +<% if template == current && template.customization_of.nil? %> +
+ <%= link_to(_('Edit template details'), '#', { class: "btn btn-default template_edit_link", role: "button" }) %> +
+<% end %> diff --git a/app/views/org_admin/templates/_templates_list.html.erb b/app/views/org_admin/templates/_templates_list.html.erb new file mode 100644 index 0000000..197890d --- /dev/null +++ b/app/views/org_admin/templates/_templates_list.html.erb @@ -0,0 +1,74 @@ +<% # locals: templates, current_org %> + +
+ + + <% if scope.length > TABLE_FILTER_MIN_ROWS %> + + + + <% end %> + + + + + + + + + + <% scope.each do |template| %> + + + + + + + + <% end %> + +
+ <%= render(partial: "shared/table_filter", locals: { placeholder: _('Search')}) %> +
<%= _('Template Name') %><%= current_user.can_super_admin? ? _('Organisation') : _('Description') %><%= _('Status') %><%= _('Edited Date') %>
+ <%= template.title %> + + <%= current_user.can_super_admin? ? template.org.name : raw(template.description) %> + + <% if !published[template.dmptemplate_id].present? %> + <%= _('Unpublished') %> + <% elsif template.dirty? %> + <%= _('Unpublished changes') %> + <% else %> + <%= _('Published') %> + <% end %> + + <% last_temp_updated = template.updated_at %> + <%= l last_temp_updated.to_date, formats: :short %> + + +
+
\ No newline at end of file diff --git a/app/views/org_admin/templates/container.html.erb b/app/views/org_admin/templates/container.html.erb new file mode 100644 index 0000000..80d2eb6 --- /dev/null +++ b/app/views/org_admin/templates/container.html.erb @@ -0,0 +1,17 @@ +
+
+

<%= template.title %>

+ <%= link_to _('View all templates'), org_admin_templates_path, class: 'btn btn-default pull-right' %> +
+
+
+
+ + <%= render partial: "/org_admin/templates/admin_nav_tabs", locals: local_assigns %> +
+
+ <%= render partial: partial_path, locals: local_assigns %> +
+
+
+
\ No newline at end of file diff --git a/app/views/org_admin/templates/history.html.erb b/app/views/org_admin/templates/history.html.erb new file mode 100644 index 0000000..5db6adb --- /dev/null +++ b/app/views/org_admin/templates/history.html.erb @@ -0,0 +1,63 @@ +
+
+

<%= _('Template History') %>

+

<%= _('Here you can view previously published versions of your template. These can no longer be modified.')%>

+
+
+ +
+
+ + <% if @templates.length > 0 then %> +
+ + + + + + + + + + + + <% @templates.each do |org_template| %> + + + + + + + + <%end%> + +
<%= _('Title') %><%= _('Version') %><%= _('Published') %><%= _('Last updated') %><%= _('Actions') %>
+ <%= org_template.title%> + <% if org_template == @current && !org_template.published%> +     <%=_('Draft')%> + <% end %> + + <%= org_template.version %> + + <%= (org_template.published? ? _('Yes') : _('No')) %> + + <% last_temp_updated = org_template.updated_at %> + <% org_template.phases.each do |phase|%> + <% if org_template.updated_at.to_date < phase.updated_at.to_date %> + <% last_temp_updated = phase.updated_at %> + <% end %> + <% end %> + <%= l last_temp_updated.to_date, formats: :short %> + + <%= link_to (org_template == @current ? _('Edit') : _('View')), edit_org_admin_template_path(id: org_template), class: "dmp_table_link"%> +
+
+ + <% else %> +

<%= _('This template is new and does not yet have any publication history.') %>

+ <% end %> +
+ <%= link_to _('View all templates'), org_admin_templates_path, class: "btn btn-default" %> +
+
+
diff --git a/app/views/org_admin/templates/index.html.erb b/app/views/org_admin/templates/index.html.erb new file mode 100644 index 0000000..2424f36 --- /dev/null +++ b/app/views/org_admin/templates/index.html.erb @@ -0,0 +1,68 @@ +<% # locals: funder_templates, org_templates, current_user, current_org, orgs %> +
+
+

<%= _('Templates') %>

+
+ <% if current_user.can_super_admin? %> +
+

<%= _('If you would like to modify one of the templates below, you must first change your organisation affiliation.') %>

+
+
+ <%= form_for current_user, url: org_swap_user_path(current_user), html: {method: :put, id: 'super-admin-switch-org'} do |f| %> + <%= render partial: "shared/my_org", locals: {f: f, default_org: current_org, orgs: orgs, allow_other_orgs: false} %> + <%= f.submit _('Change affiliation'), class: 'btn btn-default' %> + <% end %> +
+ <% end %> +
+

+ <%= _('If you wish to add an institutional template for a Data Management Plan, use the \'create template\' button. You can create more than one template if desired e.g. one for researchers and one for PhD students. Your template will be presented to users within your institution when no funder templates apply. If you want to add questions to funder templates use the \'customise template\' options below.') %> +

+
+
+ +
+
+ + +
+
+

<%= _('Organisation Templates') %>

+ <% if org_templates.length > 0 %> + <%= paginable_renderise( + partial: 'templates_list', + controller: 'org_admin/templates', + action: 'orgs', + scope: org_templates, + locals: {current_org: current_org.id, published: published}) %> + <% else %> +

<%= _('There are currently no templates defined for your organisation.') %> + <% end %> +

+
+

<%= current_user.can_super_admin? ? _('Funder Templates') : _('Customizable Templates') %>

+ <% if funder_templates.length > 0 %> + <%= paginable_renderise( + partial: 'funder_templates_list', + controller: 'org_admin/templates', + action: 'funders', + scope: funder_templates, + locals: {current_org: current_org.id, customizations: customized_templates, published: published}) %> + <% else %> +

<%= _('There are currently no funder templates.') %> + <% end %> +

+
+ + + <%= _('Create a template') %> + +
+
\ No newline at end of file diff --git a/app/views/org_admin/templates/new.html.erb b/app/views/org_admin/templates/new.html.erb new file mode 100644 index 0000000..d97cf97 --- /dev/null +++ b/app/views/org_admin/templates/new.html.erb @@ -0,0 +1,34 @@ +
+
+

+ <%= _('New template') %> +

+
+ <%= link_to _('View all templates'), org_admin_templates_path, class: "btn btn-primary" %> +
+
+
+
+
+ <%= raw _('

To create a new template, first enter a title and description. Once you have saved this you will be presented with options to add one or more phases.

')%> + <%= form_for :template, url: {action: "create"} do |f| %> +
+ <%= f.label(:title, _('Title') ,class: 'control-label') %> + <%= f.text_field :title, as: :string, + class: "form-control", "data-toggle": "tooltip", title: _('Please enter a title for your template.') %> +
+
+ <%= f.label(:description, _('Description'), class: 'control-label') %> +
+ <%= text_area_tag('template-desc', '', class: 'form-control template') %> +
+
+
+
+ <%= f.submit _('Save'), class: "btn btn-default", role:"button" %> + <%= link_to _('Cancel'), org_admin_templates_path, class: "btn btn-default", role:"button" %> +
+
+ <% end %> +
+
\ No newline at end of file diff --git a/app/views/phases/_admin_add.html.erb b/app/views/phases/_admin_add.html.erb index 2adfc78..f1b324f 100644 --- a/app/views/phases/_admin_add.html.erb +++ b/app/views/phases/_admin_add.html.erb @@ -25,6 +25,6 @@
<%= f.button(_('Save'), class: 'btn btn-default', type: "submit") %> - <%= link_to(_('Cancel'), admin_template_template_path(@template), { class: 'btn btn-default', role: "button" }) %> + <%= link_to(_('Cancel'), edit_org_admin_template_path(@template), { class: 'btn btn-default', role: "button" }) %>
<% end %> \ No newline at end of file diff --git a/app/views/phases/admin_preview.html.erb b/app/views/phases/admin_preview.html.erb index 141922d..ff2dcbe 100644 --- a/app/views/phases/admin_preview.html.erb +++ b/app/views/phases/admin_preview.html.erb @@ -8,7 +8,7 @@
@@ -17,7 +17,7 @@
- <%= render partial: "templates/admin_nav_tabs", locals: { template: @template, active: @phase.id } %> + <%= render partial: "/org_admin/templates/admin_nav_tabs", locals: { template: @template, active: @phase.id } %> <%= render partial: '/phases/edit_plan_answers', locals: { plan: nil, phase: @phase, readonly: true, question_guidance: {} } %>
diff --git a/app/views/plans/new.html.erb b/app/views/plans/new.html.erb index 48a31c0..b7c6a97 100644 --- a/app/views/plans/new.html.erb +++ b/app/views/plans/new.html.erb @@ -64,7 +64,7 @@
- <%= hidden_field_tag 'template-option-target', template_options_template_path(current_user) %> + <%= hidden_field_tag 'template-option-target', org_admin_template_options_path %>

<%= _('Which DMP template would you like to use?') %>

diff --git a/app/views/sections/_edit_section.html.erb b/app/views/sections/_edit_section.html.erb index e7cca30..f976b8d 100644 --- a/app/views/sections/_edit_section.html.erb +++ b/app/views/sections/_edit_section.html.erb @@ -29,7 +29,8 @@
<%= f.button(_('Save'), class: 'btn btn-default', type: "submit") %> - <%= link_to _('Cancel'), admin_destroy_section_path(section_id: section.id), + <%= link_to _('Cancel'), admin_show_phase_path(section.phase), class: 'btn btn-default', role: 'button' %> + <%= link_to _('Delete'), admin_destroy_section_path(section_id: section.id), confirm: _("You are about to delete '%{section_title}'. This will affect questions linked to this section. Are you sure?") % { :section_title => section.title }, method: :delete, class: 'btn btn-default', role:'button' %>
<% end %> diff --git a/app/views/templates/_admin_nav_tabs.html.erb b/app/views/templates/_admin_nav_tabs.html.erb deleted file mode 100644 index 80d8026..0000000 --- a/app/views/templates/_admin_nav_tabs.html.erb +++ /dev/null @@ -1,17 +0,0 @@ - diff --git a/app/views/templates/_admin_template.html.erb b/app/views/templates/_admin_template.html.erb deleted file mode 100644 index 7b69e49..0000000 --- a/app/views/templates/_admin_template.html.erb +++ /dev/null @@ -1,44 +0,0 @@ -
-
- <% if template == current && template.customization_of.nil? %> - - <% end %> -
-
-
-
-
- <%= render partial: "templates/show_template", locals: { template: template, current: current, template_hash: template_hash }%> -
-
-
- -
-
-
- - <% if template_hash[:template][:phases].present? %> - <% template_hash[:template][:phases].each do |phase_no, phase_hash| %> - <% phase = phase_hash[:data] %> -
- -
" class="panel-collapse collapse" role="tabpanel" aria-labelledby="<%= "headingPhase#{phase.id}" %>"> -
- <%= render partial: 'templates/show_phases_sections', locals: { phase: phase, phase_hash: phase_hash, template: template, current: current } %> -
-
-
- <% end %> - <% end %> -
-
-
diff --git a/app/views/templates/_edit_template.html.erb b/app/views/templates/_edit_template.html.erb deleted file mode 100644 index 70907af..0000000 --- a/app/views/templates/_edit_template.html.erb +++ /dev/null @@ -1,76 +0,0 @@ - -<%= form_for(template, url: admin_update_template_path(template), html: { method: :put }) do |f| %> -
- <%= f.label(:title, _('Title'), class: "control-label") %> - <%= f.text_field(:title, class: "form-control", "aria-required": false, 'data-toggle': 'tooltip', title: _('Please enter a title for your template.')) %> -
- -
- <%= f.label(:description, _('Description'), class: "control-label") %> -
- <%= text_area_tag("template-desc", template.description, { class: 'template', "aria-required": false }) %> -
-
- -
- <%= f.label _('Visibility'), class: 'control-label' %> -
- <%= f.label(:visibility, - raw("#{check_box_tag('template_visibility', '0', (template.visibility == 'organisationally_visible'))} #{_('for internal %{org_name} use only') % {org_name: @template.org.name}}")) %> -
-
- -
- <%= label_tag(:status, _('Status'), class: "control-label") %> -

- <% if template_hash[:live].nil? %> - <%= _('Unpublished') %> - <% elsif template_hash[:current].dirty? %> - <%= _('You have un-published changes') %> - <% else %> - <%= _('Published') %> - <% end %> -

-
- -
- <%= label_tag(:created_at, _('Created at'), class: "control-label") %> -

- <%= l template.created_at.to_date, formats: :short %> -

-
- -
- <%= label_tag(:updated, _('Last updated'), class: "control-label") %> -

- <%= l template.updated_at.to_date, formats: :short %> -

-
- - <% if template.org.funder? %> -
- <%= render(partial: '/shared/links', - locals: { - context: 'funder', - title: _('Funder Links'), - links: template.links['funder'], - max_number_links: MAX_NUMBER_LINKS_FUNDER, - tooltip: _('Add links to funder websites that provide additional information about the requirements for this template') }) %> -
-
- <%= render(partial: '/shared/links', - locals: { - context: 'sample_plan', - title: _('Sample Plan Links'), - links: template.links['sample_plan'], - max_number_links: MAX_NUMBER_LINKS_SAMPLE_PLAN, - tooltip: _('Add links to sample plans if provided by the funder.') }) %> -
- <%= hidden_field_tag('template-links', value: template.links) %> - <% end %> - -
- <%= f.button(_('Save'), class: 'btn btn-default', type: "submit") %> - <%= link_to(_('Cancel'), '#', { class: 'btn btn-default template_show_link', role: "button" }) %> -
-<% end %> \ No newline at end of file diff --git a/app/views/templates/_list_template.html.erb b/app/views/templates/_list_template.html.erb deleted file mode 100644 index 7c5b14b..0000000 --- a/app/views/templates/_list_template.html.erb +++ /dev/null @@ -1,89 +0,0 @@ -

- <%= title %> -

- - -<% if templates.length > 0 then %> -
- - - - - - - - - - - - <% templates.each do |hash| %> - - - - - - - - <% end %> - -
<%= _('Title') %><%= _('Description') %><%= _('Status') %><%= _('Last updated') %>
<%= hash[:current].title%><%= raw hash[:current].description.truncate(90, omission: _('... (continued)')) %> - - <% if hash[:current].customization_of.nil? %> - - <%= _('N/A') %> - <% else %> - - <% if hash[:stale] %> - <%= _('Original funder template has changed!')%> - <% elsif hash[:live].nil? %> - - <%= b_label = _('Un-published') %> - <% elsif hash[:current].dirty? %> - <%= _('You have un-published changes') %> - <% else %> - <%= _('Published') %> - <% end %> - <% end %> - - <% last_updated = hash[:current].updated_at %> - <%= l last_updated.to_date, formats: :short %> - - -
-
- <% end %> \ No newline at end of file diff --git a/app/views/templates/_show_phases_sections.html.erb b/app/views/templates/_show_phases_sections.html.erb deleted file mode 100644 index e1ab1ad..0000000 --- a/app/views/templates/_show_phases_sections.html.erb +++ /dev/null @@ -1,57 +0,0 @@ - -
-
-

- <%= raw phase.description %> -

-
-
-
-
-
- <% phase_button_text = template.customization_of.nil? ? _('Show Phase') : _('Customize Phase') %> - <%= link_to phase_button_text, admin_show_phase_path(id: phase.id), { class: "btn btn-default", role: 'button' } %> - <% if template == current && phase.modifiable %> - <%= link_to _('Delete'), admin_destroy_phase_path(phase_id: phase.id), { - confirm: _("You are about to delete '%{phase_title}'. This will affect versions, sections and questions linked to this phase. Are you sure?") % { phase_title: phase.title }, - method: :delete, - class: "btn btn-default", role: "button" } - %> - <% end %> -
-
-
-
-
- <% if phase_hash[:sections].length > 0 %> -
- - - - - - - - - <% (phase_hash[:sections].values.sort_by { |key| key[:data][:number] }).each do |section| %> - - - - - <% end %> - -
<%= _('Sections')%><%= _('Questions')%>
-

<%= section[:data].title %>

-
- <% if section[:questions].present? %> -
    - <% (section[:questions].values.sort_by { |key| key[:data][:number] }).each do |question| %> -
  • <%= raw question[:data].text %>
  • - <% end %> -
- <% end %> -
-
- <% end %> -
-
diff --git a/app/views/templates/_show_template.html.erb b/app/views/templates/_show_template.html.erb deleted file mode 100644 index f61514b..0000000 --- a/app/views/templates/_show_template.html.erb +++ /dev/null @@ -1,35 +0,0 @@ - -
-
<%= _('Title') %>
-
<%= template.title %>
-
<%= _('Description') %>
-
- <%= (!template.description.nil? && template.description != "" ? raw( template.description) : '-') %> -
-
<%= _('Status') %>
-
- <% if template_hash[:live].nil? %> - <%= _('Unpublished') %> - - <% elsif template_hash[:current].dirty? %> - <%= _('You have un-published changes') %> - - <% else %> - <%= _('Published') %> - <% end %> -
- <% if template.org.funder? %> -
<%= _('Visibility') %>
-
<%= (template.visibility == 'organisationally_visible' ? _('for internal %{org_name} use only') % {org_name: @template.org.name} : _('available to the public') + (template_hash[:live].nil? ? ' (once published)' : '')) %>
- <% end %> -
<%= _('Created at') %>
-
<%= l template.created_at.to_date, formats: :short %>
-
<%= _('Last updated') %>
-
<%= l template.updated_at.to_date, formats: :short %>
-
- -<% if template == current && template.customization_of.nil? %> -
- <%= link_to(_('Edit template details'), '#', { class: "btn btn-default template_edit_link", role: "button" }) %> -
-<% end %> diff --git a/app/views/templates/admin_index.html.erb b/app/views/templates/admin_index.html.erb deleted file mode 100644 index 41c72a5..0000000 --- a/app/views/templates/admin_index.html.erb +++ /dev/null @@ -1,92 +0,0 @@ -
-
-

<%= _('Templates') %>

-

- <%= _("If you wish to add an institutional template for a Data Management Plan, use the 'create template' button. You can create more than one template if desired e.g. one for researchers and one for PhD students.") %> -

-

- <%= _("Your template will be presented to users within your institution when no funder templates apply. If you want to add questions to funder templates use the 'customise template' options below.") %> -

-
-
- -
-
-

- <%= _('Own templates') %> -

- - <% if @org_templates.length > 0 then %> -
- - - - - - - - - - - - <% @org_templates.each do |hash| %> - - - - - - - - <% end %> - -
<%= _('Title') %><%= _('Description') %><%= _('Status') %><%= _('Last updated') %>
- <%= hash[:current].title %> - - <%= raw hash[:current].description.truncate(90, omission: _('... (continued)')) unless hash[:current].description.nil? %> - - <% if hash[:live].nil? %> - <%= _('Unpublished') %> - - <% elsif hash[:current].dirty? %> - <%= _('Unpublished changes') %> - - <% else %> - <%= _('Published') %> - <% end %> - - <% last_temp_updated = hash[:current].updated_at %> - <%= l last_temp_updated.to_date, formats: :short %> - -
-
- <% end %> - - - <%= _('Create a template') %> - - <%= render partial: '/templates/list_template', locals: { title: n_('Default template', 'Default templates', @organisation_templates.length), templates: @organisation_templates } %> - - <% if !current_user.org.funder? %> - <%= render partial: '/templates/list_template', locals: { title: _('Funders templates'), templates: @funder_templates } %> - <% end %> -
-
diff --git a/app/views/templates/admin_new.html.erb b/app/views/templates/admin_new.html.erb deleted file mode 100644 index 37b0cf3..0000000 --- a/app/views/templates/admin_new.html.erb +++ /dev/null @@ -1,34 +0,0 @@ -
-
-

- <%= _('New template') %> -

-
- <%= link_to _('View all templates'), admin_index_template_path, class: "btn btn-primary" %> -
-
-
-
-
- <%= raw _('

To create a new template, first enter a title and description. Once you have saved this you will be presented with options to add one or more phases.

')%> - <%= form_for :template, url: {action: "admin_create"} do |f| %> -
- <%= f.label(:title, _('Title') ,class: 'control-label') %> - <%= f.text_field :title, as: :string, - class: "form-control", "data-toggle": "tooltip", title: _('Please enter a title for your template.') %> -
-
- <%= f.label(:description, _('Description'), class: 'control-label') %> -
- <%= text_area_tag('template-desc', '', class: 'form-control template') %> -
-
-
-
- <%= f.submit _('Save'), class: "btn btn-default", role:"button" %> - <%= link_to _('Cancel'), admin_index_template_path, class: "btn btn-default", role:"button" %> -
-
- <% end %> -
-
\ No newline at end of file diff --git a/app/views/templates/admin_template_history.html.erb b/app/views/templates/admin_template_history.html.erb deleted file mode 100644 index ab4239a..0000000 --- a/app/views/templates/admin_template_history.html.erb +++ /dev/null @@ -1,63 +0,0 @@ -
-
-

<%= _('Template History') %>

-

<%= _('Here you can view previously published versions of your template. These can no longer be modified.')%>

-
-
- -
-
- - <% if @templates.length > 0 then %> -
- - - - - - - - - - - - <% @templates.each do |org_template| %> - - - - - - - - <%end%> - -
<%= _('Title') %><%= _('Version') %><%= _('Published') %><%= _('Last updated') %><%= _('Actions') %>
- <%= org_template.title%> - <% if org_template == @current && !org_template.published%> -     <%=_('Draft')%> - <% end %> - - <%= org_template.version %> - - <%= (org_template.published? ? _('Yes') : _('No')) %> - - <% last_temp_updated = org_template.updated_at %> - <% org_template.phases.each do |phase|%> - <% if org_template.updated_at.to_date < phase.updated_at.to_date %> - <% last_temp_updated = phase.updated_at %> - <% end %> - <% end %> - <%= l last_temp_updated.to_date, formats: :short %> - - <%= link_to (org_template == @current ? _('Edit') : _('View')), admin_template_template_path(id: org_template), class: "dmp_table_link"%> -
-
- - <% else %> -

<%= _('This template is new and does not yet have any publication history.') %>

- <% end %> -
- <%= link_to _('View all templates'), admin_index_template_path, class: "btn btn-default" %> -
-
-
diff --git a/app/views/templates/container.html.erb b/app/views/templates/container.html.erb deleted file mode 100644 index 6dc657a..0000000 --- a/app/views/templates/container.html.erb +++ /dev/null @@ -1,16 +0,0 @@ -
-
-

<%= template.title %>

-
-
-
-
- - <%= render partial: "templates/admin_nav_tabs", locals: local_assigns %> -
-
- <%= render partial: partial_path, locals: local_assigns %> -
-
-
-
\ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 6b03151..c66fa7d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -59,6 +59,7 @@ resources :users, path: 'users', only: [] do member do put 'update_email_preferences' + put 'org_swap', constraints: {format: [:json]} end end @@ -133,24 +134,6 @@ end end - resources :templates, :path => 'org/admin/templates', only: [] do - member do - get 'admin_index' - get 'admin_template' - get 'admin_new' - get 'admin_template_history' - get 'admin_customize' - delete 'admin_destroy' - post 'admin_create' - put 'admin_update' - put 'admin_publish' - put 'admin_unpublish' - put 'admin_copy' - get 'admin_transfer_customization' - get 'template_options', constraints: {format: [:json]} - end - end - resources :phases, path: 'org/admin/templates/phases', only: [] do member do get 'admin_show' @@ -285,6 +268,22 @@ get 'feedback_complete' end end + resources :templates, only: [:index, :new, :create, :edit, :update, :destroy] do + member do + get 'history' + get 'customize' + get 'transfer_customization' + get 'copy', action: :copy, constraints: {format: [:json]} + get 'publish', action: :publish, constraints: {format: [:json]} + get 'unpublish', action: :unpublish, constraints: {format: [:json]} + end + + # pagination + get 'funders/:page', action: :funders, on: :collection, as: :funders + get 'orgs/:page', action: :orgs, on: :collection, as: :orgs + end + + get 'template_options' => 'templates#template_options', constraints: {format: [:json]} end namespace :super_admin do diff --git a/db/schema.rb b/db/schema.rb index d7b031d..7ba7c37 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -13,70 +13,74 @@ ActiveRecord::Schema.define(version: 20171124133802) do - # These are extensions that must be enabled in order to support this database - enable_extension "plpgsql" - create_table "annotations", force: :cascade do |t| - t.integer "question_id" - t.integer "org_id" - t.text "text" - t.integer "type", default: 0, null: false + t.integer "question_id", limit: 4 + t.integer "org_id", limit: 4 + t.text "text", limit: 65535 + t.integer "type", limit: 4, default: 0, null: false t.datetime "created_at" t.datetime "updated_at" end + add_index "annotations", ["org_id"], name: "fk_rails_aca7521f72", using: :btree + add_index "annotations", ["question_id"], name: "fk_rails_0e08e753b6", using: :btree add_index "annotations", ["question_id"], name: "index_annotations_on_question_id", using: :btree create_table "answers", force: :cascade do |t| - t.text "text" - t.integer "plan_id" - t.integer "user_id" - t.integer "question_id" + t.text "text", limit: 65535 + t.integer "plan_id", limit: 4 + t.integer "user_id", limit: 4 + t.integer "question_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" - t.integer "lock_version", default: 0 + t.integer "lock_version", limit: 4, default: 0 + t.string "label_id", limit: 255 end + add_index "answers", ["plan_id"], name: "fk_rails_84a6005a3e", using: :btree + add_index "answers", ["question_id"], name: "fk_rails_3d5ed4418f", using: :btree + add_index "answers", ["user_id"], name: "fk_rails_584be190c2", using: :btree + create_table "answers_question_options", id: false, force: :cascade do |t| - t.integer "answer_id", null: false - t.integer "question_option_id", null: false + t.integer "answer_id", limit: 4, null: false + t.integer "question_option_id", limit: 4, null: false end add_index "answers_question_options", ["answer_id"], name: "index_answers_question_options_on_answer_id", using: :btree create_table "exported_plans", force: :cascade do |t| - t.integer "plan_id" - t.integer "user_id" - t.string "format" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.integer "phase_id" + t.integer "plan_id", limit: 4 + t.integer "user_id", limit: 4 + t.string "format", limit: 255 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "phase_id", limit: 4 end create_table "file_types", force: :cascade do |t| - t.string "name" - t.string "icon_name" - t.integer "icon_size" - t.string "icon_location" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.string "name", limit: 255 + t.string "icon_name", limit: 255 + t.integer "icon_size", limit: 4 + t.string "icon_location", limit: 255 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end create_table "file_uploads", force: :cascade do |t| - t.string "name" - t.string "title" - t.text "description" - t.integer "size" + t.string "name", limit: 255 + t.string "title", limit: 255 + t.text "description", limit: 65535 + t.integer "size", limit: 4 t.boolean "published" - t.string "location" - t.integer "file_type_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.string "location", limit: 255 + t.integer "file_type_id", limit: 4 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end create_table "friendly_id_slugs", force: :cascade do |t| - t.string "slug", null: false - t.integer "sluggable_id", null: false + t.string "slug", limit: 255, null: false + t.integer "sluggable_id", limit: 4, null: false t.string "sluggable_type", limit: 40 t.datetime "created_at" end @@ -86,340 +90,384 @@ add_index "friendly_id_slugs", ["sluggable_type"], name: "index_friendly_id_slugs_on_sluggable_type", using: :btree create_table "guidance_groups", force: :cascade do |t| - t.string "name" - t.integer "org_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.string "name", limit: 255 + t.integer "org_id", limit: 4 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.boolean "optional_subset" t.boolean "published" end + add_index "guidance_groups", ["org_id"], name: "fk_rails_819c1dbbc7", using: :btree add_index "guidance_groups", ["org_id"], name: "index_guidance_groups_on_org_id", using: :btree create_table "guidances", force: :cascade do |t| - t.text "text" - t.integer "guidance_group_id" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.integer "question_id" + t.text "text", limit: 65535 + t.integer "guidance_group_id", limit: 4 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "question_id", limit: 4 t.boolean "published" end + add_index "guidances", ["guidance_group_id"], name: "fk_rails_20d29da787", using: :btree add_index "guidances", ["guidance_group_id"], name: "index_guidances_on_guidance_group_id", using: :btree create_table "identifier_schemes", force: :cascade do |t| - t.string "name" - t.string "description" + t.string "name", limit: 255 + t.string "description", limit: 255 t.boolean "active" t.datetime "created_at" t.datetime "updated_at" - t.string "logo_url" - t.string "user_landing_url" + t.string "logo_url", limit: 255 + t.string "user_landing_url", limit: 255 end create_table "languages", force: :cascade do |t| - t.string "abbreviation" - t.string "description" - t.string "name" + t.string "abbreviation", limit: 255 + t.string "description", limit: 255 + t.string "name", limit: 255 t.boolean "default_language" end create_table "notes", force: :cascade do |t| - t.integer "user_id" - t.text "text" + t.integer "user_id", limit: 4 + t.text "text", limit: 65535 t.boolean "archived" - t.integer "answer_id" - t.integer "archived_by" + t.integer "answer_id", limit: 4 + t.integer "archived_by", limit: 4 t.datetime "created_at" t.datetime "updated_at" end + add_index "notes", ["answer_id"], name: "fk_rails_907f8d48bf", using: :btree add_index "notes", ["answer_id"], name: "index_notes_on_answer_id", using: :btree + add_index "notes", ["user_id"], name: "fk_rails_7f2323ad43", using: :btree create_table "org_identifiers", force: :cascade do |t| - t.string "identifier" - t.string "attrs" + t.string "identifier", limit: 255 + t.string "attrs", limit: 255 t.datetime "created_at" t.datetime "updated_at" - t.integer "org_id" - t.integer "identifier_scheme_id" + t.integer "org_id", limit: 4 + t.integer "identifier_scheme_id", limit: 4 end + add_index "org_identifiers", ["identifier_scheme_id"], name: "fk_rails_189ad2e573", using: :btree + add_index "org_identifiers", ["org_id"], name: "fk_rails_36323c0674", using: :btree + create_table "org_token_permissions", force: :cascade do |t| - t.integer "org_id" - t.integer "token_permission_type_id" + t.integer "org_id", limit: 4 + t.integer "token_permission_type_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" end + add_index "org_token_permissions", ["org_id"], name: "fk_rails_e1db1b22c5", using: :btree add_index "org_token_permissions", ["org_id"], name: "index_org_token_permissions_on_org_id", using: :btree + add_index "org_token_permissions", ["token_permission_type_id"], name: "fk_rails_2aa265f538", using: :btree create_table "orgs", force: :cascade do |t| - t.string "name" - t.string "abbreviation" - t.string "target_url" - t.string "wayfless_entity" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.integer "parent_id" + t.string "name", limit: 255 + t.string "abbreviation", limit: 255 + t.string "target_url", limit: 255 + t.string "wayfless_entity", limit: 255 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.integer "parent_id", limit: 4 t.boolean "is_other" - t.string "sort_name" - t.text "banner_text" - t.string "logo_file_name" - t.integer "region_id" - t.integer "language_id" - t.string "logo_uid" - t.string "logo_name" - t.string "contact_email" - t.integer "org_type", default: 0, null: false - t.string "links", default: "[]" - t.string "contact_name" - t.boolean "feedback_enabled", default: false - t.string "feedback_email_subject" - t.text "feedback_email_msg" + t.string "sort_name", limit: 255 + t.text "banner_text", limit: 65535 + t.string "logo_file_name", limit: 255 + t.integer "region_id", limit: 4 + t.integer "language_id", limit: 4 + t.string "logo_uid", limit: 255 + t.string "logo_name", limit: 255 + t.string "contact_email", limit: 255 + t.integer "org_type", limit: 4, default: 0, null: false + t.string "contact_name", limit: 255 + t.string "links", limit: 255, default: "[]" + t.boolean "feedback_enabled", default: false + t.string "feedback_email_subject", limit: 255 + t.text "feedback_email_msg", limit: 65535 end + add_index "orgs", ["language_id"], name: "fk_rails_5640112cab", using: :btree + add_index "orgs", ["region_id"], name: "fk_rails_5a6adf6bab", using: :btree + create_table "perms", force: :cascade do |t| - t.string "name" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.string "name", limit: 255 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end add_index "perms", ["name"], name: "index_perms_on_name", using: :btree add_index "perms", ["name"], name: "index_roles_on_name_and_resource_type_and_resource_id", using: :btree create_table "phases", force: :cascade do |t| - t.string "title" - t.text "description" - t.integer "number" - t.integer "template_id" + t.string "title", limit: 255 + t.text "description", limit: 65535 + t.integer "number", limit: 4 + t.integer "template_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" - t.string "slug" + t.string "slug", limit: 255 t.boolean "modifiable" end add_index "phases", ["template_id"], name: "index_phases_on_template_id", using: :btree create_table "plans", force: :cascade do |t| - t.string "title" - t.integer "template_id" + t.string "title", limit: 255 + t.integer "template_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" - t.string "slug" - t.string "grant_number" - t.string "identifier" - t.text "description" - t.string "principal_investigator" - t.string "principal_investigator_identifier" - t.string "data_contact" - t.string "funder_name" - t.integer "visibility", null: false - t.string "data_contact_email" - t.string "data_contact_phone" - t.string "principal_investigator_email" - t.string "principal_investigator_phone" - t.boolean "feedback_requested", default: false + t.string "slug", limit: 255 + t.string "data_contact_phone", limit: 255 + t.string "grant_number", limit: 255 + t.string "identifier", limit: 255 + t.text "description", limit: 65535 + t.string "principal_investigator", limit: 255 + t.string "principal_investigator_identifier", limit: 255 + t.string "data_contact", limit: 255 + t.string "funder_name", limit: 255 + t.integer "visibility", limit: 4, null: false + t.string "data_contact_email", limit: 255 + t.string "principal_investigator_email", limit: 255 + t.string "principal_investigator_phone", limit: 255 + t.boolean "feedback_requested", default: false end add_index "plans", ["template_id"], name: "index_plans_on_template_id", using: :btree create_table "plans_guidance_groups", force: :cascade do |t| - t.integer "guidance_group_id" - t.integer "plan_id" + t.integer "guidance_group_id", limit: 4 + t.integer "plan_id", limit: 4 end + add_index "plans_guidance_groups", ["guidance_group_id"], name: "fk_rails_ec1c5524d7", using: :btree + add_index "plans_guidance_groups", ["plan_id"], name: "fk_rails_13d0671430", using: :btree + create_table "prefs", force: :cascade do |t| - t.text "settings" - t.integer "user_id" + t.text "settings", limit: 65535 + t.integer "user_id", limit: 4 + end + + create_table "question_format_labels", id: false, force: :cascade do |t| + t.integer "id", limit: 4 + t.string "description", limit: 255 + t.integer "question_id", limit: 4 + t.integer "number", limit: 4 + t.datetime "created_at" + t.datetime "updated_at" end create_table "question_formats", force: :cascade do |t| - t.string "title" - t.text "description" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.boolean "option_based", default: false - t.integer "formattype", default: 0 + t.string "title", limit: 255 + t.text "description", limit: 65535 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.boolean "option_based", default: false + t.integer "formattype", limit: 4, default: 0 end create_table "question_options", force: :cascade do |t| - t.integer "question_id" - t.string "text" - t.integer "number" + t.integer "question_id", limit: 4 + t.string "text", limit: 255 + t.integer "number", limit: 4 t.boolean "is_default" t.datetime "created_at" t.datetime "updated_at" end + add_index "question_options", ["question_id"], name: "fk_rails_b9c5f61cf9", using: :btree add_index "question_options", ["question_id"], name: "index_question_options_on_question_id", using: :btree create_table "questions", force: :cascade do |t| - t.text "text" - t.text "default_value" - t.integer "number" - t.integer "section_id" + t.text "text", limit: 65535 + t.text "default_value", limit: 65535 + t.integer "number", limit: 4 + t.integer "section_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" - t.integer "question_format_id" - t.boolean "option_comment_display", default: true + t.integer "question_format_id", limit: 4 + t.boolean "option_comment_display", default: true t.boolean "modifiable" end + add_index "questions", ["question_format_id"], name: "fk_rails_4fbc38c8c7", using: :btree add_index "questions", ["section_id"], name: "index_questions_on_section_id", using: :btree create_table "questions_themes", id: false, force: :cascade do |t| - t.integer "question_id", null: false - t.integer "theme_id", null: false + t.integer "question_id", limit: 4, null: false + t.integer "theme_id", limit: 4, null: false end add_index "questions_themes", ["question_id"], name: "index_questions_themes_on_question_id", using: :btree create_table "regions", force: :cascade do |t| - t.string "abbreviation" - t.string "description" - t.string "name" - t.integer "super_region_id" + t.string "abbreviation", limit: 255 + t.string "description", limit: 255 + t.string "name", limit: 255 + t.integer "super_region_id", limit: 4 end create_table "roles", force: :cascade do |t| - t.integer "user_id" - t.integer "plan_id" + t.integer "user_id", limit: 4 + t.integer "plan_id", limit: 4 t.datetime "created_at" t.datetime "updated_at" - t.integer "access", default: 0, null: false - t.boolean "active", default: true + t.integer "access", limit: 4, default: 0, null: false + t.boolean "active", default: true end + add_index "roles", ["plan_id"], name: "fk_rails_a1ce6c2772", using: :btree add_index "roles", ["plan_id"], name: "index_roles_on_plan_id", using: :btree + add_index "roles", ["user_id"], name: "fk_rails_ab35d699f0", using: :btree add_index "roles", ["user_id"], name: "index_roles_on_user_id", using: :btree + create_table "sample_plans", id: false, force: :cascade do |t| + t.integer "id", limit: 4 + t.string "url", limit: 255 + t.string "label", limit: 255 + t.integer "template_id", limit: 4 + t.datetime "created_at" + t.datetime "updated_at" + end + create_table "sections", force: :cascade do |t| - t.string "title" - t.text "description" - t.integer "number" + t.string "title", limit: 255 + t.text "description", limit: 65535 + t.integer "number", limit: 4 t.datetime "created_at" t.datetime "updated_at" t.boolean "published" - t.integer "phase_id" + t.integer "phase_id", limit: 4 t.boolean "modifiable" end add_index "sections", ["phase_id"], name: "index_sections_on_phase_id", using: :btree create_table "settings", force: :cascade do |t| - t.string "var", null: false - t.text "value" - t.integer "target_id", null: false - t.string "target_type", null: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.string "var", limit: 255, null: false + t.text "value", limit: 65535 + t.integer "target_id", limit: 4, null: false + t.string "target_type", limit: 255, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end add_index "settings", ["target_type", "target_id", "var"], name: "index_settings_on_target_type_and_target_id_and_var", unique: true, using: :btree create_table "splash_logs", force: :cascade do |t| - t.string "destination" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.string "destination", limit: 255 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end create_table "templates", force: :cascade do |t| - t.string "title" - t.text "description" + t.string "title", limit: 255 + t.text "description", limit: 65535 t.boolean "published" - t.integer "org_id" - t.string "locale" + t.integer "org_id", limit: 4 + t.string "locale", limit: 255 t.boolean "is_default" t.datetime "created_at" t.datetime "updated_at" - t.integer "version" - t.integer "visibility" - t.integer "customization_of" - t.integer "dmptemplate_id" + t.integer "version", limit: 4 + t.integer "visibility", limit: 4 + t.integer "customization_of", limit: 4 + t.integer "dmptemplate_id", limit: 4 t.boolean "migrated" - t.boolean "dirty", default: false - t.string "links", default: "{\"funder\":[], \"sample_plan\":[]}" + t.boolean "dirty", default: false + t.string "links", limit: 255, default: "{\"funder\":[], \"sample_plan\":[]}" end add_index "templates", ["org_id", "dmptemplate_id"], name: "template_organisation_dmptemplate_index", using: :btree add_index "templates", ["org_id"], name: "index_templates_on_org_id", using: :btree create_table "themes", force: :cascade do |t| - t.string "title" - t.text "description" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "locale" + t.string "title", limit: 255 + t.text "description", limit: 65535 + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.string "locale", limit: 255 end create_table "themes_in_guidance", id: false, force: :cascade do |t| - t.integer "theme_id" - t.integer "guidance_id" + t.integer "theme_id", limit: 4 + t.integer "guidance_id", limit: 4 end + add_index "themes_in_guidance", ["guidance_id"], name: "fk_rails_a5ab9402df", using: :btree add_index "themes_in_guidance", ["guidance_id"], name: "index_themes_in_guidance_on_guidance_id", using: :btree + add_index "themes_in_guidance", ["theme_id"], name: "fk_rails_7d708f6f1e", using: :btree add_index "themes_in_guidance", ["theme_id"], name: "index_themes_in_guidance_on_theme_id", using: :btree create_table "token_permission_types", force: :cascade do |t| - t.string "token_type" - t.text "text_description" + t.string "token_type", limit: 255 + t.text "text_description", limit: 65535 t.datetime "created_at" t.datetime "updated_at" end create_table "user_identifiers", force: :cascade do |t| - t.string "identifier" + t.string "identifier", limit: 255 t.datetime "created_at" t.datetime "updated_at" - t.integer "user_id" - t.integer "identifier_scheme_id" + t.integer "user_id", limit: 4 + t.integer "identifier_scheme_id", limit: 4 end + add_index "user_identifiers", ["identifier_scheme_id"], name: "fk_rails_fe95df7db0", using: :btree + add_index "user_identifiers", ["user_id"], name: "fk_rails_65c9a98cdb", using: :btree add_index "user_identifiers", ["user_id"], name: "index_user_identifiers_on_user_id", using: :btree create_table "users", force: :cascade do |t| - t.string "firstname" - t.string "surname" - t.string "email", default: "", null: false - t.string "orcid_id" - t.string "shibboleth_id" + t.string "firstname", limit: 255 + t.string "surname", limit: 255 + t.string "email", limit: 255, default: "", null: false + t.string "orcid_id", limit: 255 + t.string "shibboleth_id", limit: 255 t.datetime "created_at" t.datetime "updated_at" - t.string "encrypted_password", default: "" - t.string "reset_password_token" + t.string "encrypted_password", limit: 255, default: "" + t.string "reset_password_token", limit: 255 t.datetime "reset_password_sent_at" t.datetime "remember_created_at" - t.integer "sign_in_count", default: 0 + t.integer "sign_in_count", limit: 4, default: 0 t.datetime "current_sign_in_at" t.datetime "last_sign_in_at" - t.string "current_sign_in_ip" - t.string "last_sign_in_ip" - t.string "confirmation_token" + t.string "current_sign_in_ip", limit: 255 + t.string "last_sign_in_ip", limit: 255 + t.string "confirmation_token", limit: 255 t.datetime "confirmed_at" t.datetime "confirmation_sent_at" - t.string "invitation_token" + t.string "invitation_token", limit: 255 t.datetime "invitation_created_at" t.datetime "invitation_sent_at" t.datetime "invitation_accepted_at" - t.string "other_organisation" + t.string "other_organisation", limit: 255 t.boolean "accept_terms" - t.integer "org_id" - t.string "api_token" - t.integer "invited_by_id" - t.string "invited_by_type" - t.integer "language_id" - t.string "recovery_email" + t.integer "org_id", limit: 4 + t.string "api_token", limit: 255 + t.integer "invited_by_id", limit: 4 + t.string "invited_by_type", limit: 255 + t.integer "language_id", limit: 4 + t.string "recovery_email", limit: 255 end add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree + add_index "users", ["language_id"], name: "fk_rails_45f4f12508", using: :btree + add_index "users", ["org_id"], name: "fk_rails_e73753bccb", using: :btree add_index "users", ["org_id"], name: "index_users_on_org_id", using: :btree create_table "users_perms", id: false, force: :cascade do |t| - t.integer "user_id" - t.integer "perm_id" + t.integer "user_id", limit: 4 + t.integer "perm_id", limit: 4 end + add_index "users_perms", ["perm_id"], name: "fk_rails_457217c31c", using: :btree add_index "users_perms", ["user_id"], name: "index_users_perms_on_user_id", using: :btree add_foreign_key "annotations", "orgs" @@ -427,8 +475,6 @@ add_foreign_key "answers", "plans" add_foreign_key "answers", "questions" add_foreign_key "answers", "users" - add_foreign_key "answers_question_options", "answers" - add_foreign_key "answers_question_options", "question_options" add_foreign_key "guidance_groups", "orgs" add_foreign_key "guidances", "guidance_groups" add_foreign_key "notes", "answers" @@ -446,8 +492,6 @@ add_foreign_key "question_options", "questions" add_foreign_key "questions", "question_formats" add_foreign_key "questions", "sections" - add_foreign_key "questions_themes", "questions" - add_foreign_key "questions_themes", "themes" add_foreign_key "roles", "plans" add_foreign_key "roles", "users" add_foreign_key "sections", "phases" @@ -458,6 +502,4 @@ add_foreign_key "user_identifiers", "users" add_foreign_key "users", "languages" add_foreign_key "users", "orgs" - add_foreign_key "users_perms", "perms" - add_foreign_key "users_perms", "users" end diff --git a/lib/assets/javascripts/application.js b/lib/assets/javascripts/application.js index e1ecbcf..88b1a1f 100644 --- a/lib/assets/javascripts/application.js +++ b/lib/assets/javascripts/application.js @@ -21,6 +21,9 @@ import './views/guidances/admin_edit'; import './views/guidances/admin_new'; import './views/notes/index'; +import './views/org_admin/templates/edit'; +import './views/org_admin/templates/index'; +import './views/org_admin/templates/show'; import './views/orgs/admin_edit'; import './views/orgs/shibboleth_ds'; import './views/phases/edit'; @@ -42,7 +45,5 @@ import './views/shared/create_account_form'; import './views/shared/my_org'; import './views/shared/sign_in_form'; -import './views/templates/edit'; -import './views/templates/show'; import './views/themes/new_edit'; import './views/users/notification_preferences'; diff --git a/lib/assets/javascripts/views/org_admin/templates/edit.js b/lib/assets/javascripts/views/org_admin/templates/edit.js new file mode 100644 index 0000000..f3dbc54 --- /dev/null +++ b/lib/assets/javascripts/views/org_admin/templates/edit.js @@ -0,0 +1,19 @@ +import { Tinymce } from '../../../utils/tinymce'; +import { eachLinks } from '../../../utils/links'; + +$(() => { + Tinymce.init({ selector: '.template' }); + $('.template_show_link').on('click', (e) => { + e.preventDefault(); + $(e.target).closest('.template_edit').hide(); + $(e.target).closest('.tab-pane').find('.template_show').show(); + }); + $('.edit_template').on('submit', () => { + const links = {}; + eachLinks((ctx, value) => { + links[ctx] = value; + }).done(() => { + $('#template-links').val(JSON.stringify(links)); + }); + }); +}); diff --git a/lib/assets/javascripts/views/org_admin/templates/index.js b/lib/assets/javascripts/views/org_admin/templates/index.js new file mode 100644 index 0000000..086e10a --- /dev/null +++ b/lib/assets/javascripts/views/org_admin/templates/index.js @@ -0,0 +1,46 @@ +import * as notifications from '../../../utils/notificationHelper'; +import { isObject } from '../../../utils/isType'; +import { isValidNumber } from '../../../utils/isValidInputType'; + +$(() => { + // enable the Actions dropdown for each template belonging to the current user's org + const enableActions = (ctx) => { + if (isValidNumber($(ctx).find('#user_org_id').val())) { + $('tr .dropdown .super-admin-template-org').map((idx, el) => { + if (isValidNumber($(el).text()) && $(ctx).find('#user_org_id').val().toString() === $(el).text()) { + $(el).parent().removeClass('hide'); + } else { + $(el).parent().addClass('hide'); + } + return true; + }); + } + }; + const swapOrg = (ctx) => { + if (isValidNumber($(ctx).find('#user_org_id').val())) { + notifications.hideNotifications(); + $.ajax({ + method: $(ctx).attr('method'), + url: $(ctx).attr('action'), + data: $(ctx).serializeArray(), + }).done((data) => { + if (data.msg.length > 0) { + notifications.renderNotice(data.msg); + } else if (data.err.length > 0) { + notifications.renderAlert(data.err); + } + enableActions(ctx); + }).fail((err) => { + notifications.renderAlert(err); + }); + } + }; + + if (isObject($('form#super-admin-switch-org'))) { + $('form#super-admin-switch-org').on('submit', (e) => { + e.preventDefault(); + swapOrg(e.target); + }); + enableActions($('form#super-admin-switch-org')); + } +}); diff --git a/lib/assets/javascripts/views/org_admin/templates/show.js b/lib/assets/javascripts/views/org_admin/templates/show.js new file mode 100644 index 0000000..fd89a07 --- /dev/null +++ b/lib/assets/javascripts/views/org_admin/templates/show.js @@ -0,0 +1,7 @@ +$(() => { + $('.template_edit_link').on('click', (e) => { + e.preventDefault(); + $(e.target).closest('.template_show').hide(); + $(e.target).closest('.tab-pane').find('.template_edit').show(); + }); +}); diff --git a/lib/assets/javascripts/views/templates/edit.js b/lib/assets/javascripts/views/templates/edit.js deleted file mode 100644 index 448a8c7..0000000 --- a/lib/assets/javascripts/views/templates/edit.js +++ /dev/null @@ -1,19 +0,0 @@ -import { Tinymce } from '../../utils/tinymce'; -import { eachLinks } from '../../utils/links'; - -$(() => { - Tinymce.init({ selector: '.template' }); - $('.template_show_link').on('click', (e) => { - e.preventDefault(); - $(e.target).closest('.template_edit').hide(); - $(e.target).closest('.tab-pane').find('.template_show').show(); - }); - $('.edit_template').on('submit', () => { - const links = {}; - eachLinks((ctx, value) => { - links[ctx] = value; - }).done(() => { - $('#template-links').val(JSON.stringify(links)); - }); - }); -}); diff --git a/lib/assets/javascripts/views/templates/show.js b/lib/assets/javascripts/views/templates/show.js deleted file mode 100644 index fd89a07..0000000 --- a/lib/assets/javascripts/views/templates/show.js +++ /dev/null @@ -1,7 +0,0 @@ -$(() => { - $('.template_edit_link').on('click', (e) => { - e.preventDefault(); - $(e.target).closest('.template_show').hide(); - $(e.target).closest('.tab-pane').find('.template_edit').show(); - }); -}); diff --git a/test/functional/phases_controller_test.rb b/test/functional/phases_controller_test.rb index 68b839f..c0648d3 100644 --- a/test/functional/phases_controller_test.rb +++ b/test/functional/phases_controller_test.rb @@ -221,7 +221,7 @@ delete admin_destroy_phase_path(id: @template.phases.first.id, phase_id: id) assert_response :redirect - assert_redirected_to admin_template_template_path(@template) + assert_redirected_to edit_org_admin_template_path(@template) assert flash[:notice].start_with?('Successfully') && flash[:notice].include?('deleted') assert_raise ActiveRecord::RecordNotFound do Phase.find(id).nil? diff --git a/test/functional/public_pages_controller_test.rb b/test/functional/public_pages_controller_test.rb index 182b9f4..6dd41a3 100644 --- a/test/functional/public_pages_controller_test.rb +++ b/test/functional/public_pages_controller_test.rb @@ -17,13 +17,14 @@ roles: [Role.new(user: User.last, creator: true)]) end - @inst_tmplt = Template.create!(title: 'Inst template', org: Org.institutions.first, migrated: false, published: true) - @dflt_tmplt = Template.create!(title: 'Dflt template', org: Org.managing_orgs.first, migrated: false, published: true, is_default: true) - @fndr_tmplt = Template.create!(title: 'Fndr template', org: Org.funders.first, migrated: false, published: true) + @inst_tmplt = Template.create!(title: 'Inst template', org: Org.institution.first, migrated: false, published: true) + @dflt_tmplt = Template.create!(title: 'Dflt template', org: Org.managing_orgs.first, migrated: false, published: true) + @fndr_tmplt = Template.create!(title: 'Fndr template', org: Org.funder.first, migrated: false, published: true) [@inst_tmplt, @dflt_tmplt, @fndr_tmplt].each do |t| t.published = true t.is_default = true if t == @dflt_tmplt + t.visibility = t.title != 'Inst template' ? Template.visibilities[:publicly_visible] : Template.visibilities[:organisationally_visible] t.save! end diff --git a/test/functional/templates_controller_test.rb b/test/functional/templates_controller_test.rb index baba40d..36d4a3c 100644 --- a/test/functional/templates_controller_test.rb +++ b/test/functional/templates_controller_test.rb @@ -9,61 +9,49 @@ # Get the first Org Admin scaffold_org_admin(@template.org) + + @regular_user = User.find_by(email: 'org_user@example.com') end -# TODO: The following methods SHOULD replace the old 'admin_' prefixed methods. The routes file already has -# these defined. We should remove the old routes to the 'admin_' prefixed methods as well. We should just -# have: -# -# SHOULD BE: -# -------------------------------------------------- -# templates GET /templates templates#index -# POST /templates templates#create -# template GET /template/[:id] templates#show -# PATCH /template/[:id] templates#update -# PUT /template/[:id] templates#update -# DELETE /template/[:id] templates#destroy -# edit_template GET /template/[:id]/edit templates#edit -# new_template GET /templates/new templates#new -# -# -# CURRENT RESULTS OF `rake routes` -# -------------------------------------------------- -# admin_index_template GET /org/admin/templates/:id/admin_index(.:format) templates#admin_index -# admin_template_template GET /org/admin/templates/:id/admin_template(.:format) templates#admin_template -# admin_new_template GET /org/admin/templates/:id/admin_new(.:format) templates#admin_new -# admin_template_history_template GET /org/admin/templates/:id/admin_template_history(.:format) templates#admin_template_history -# admin_destroy_template DELETE /org/admin/templates/:id/admin_destroy(.:format) templates#admin_destroy -# admin_create_template POST /org/admin/templates/:id/admin_create(.:format) templates#admin_create -# admin_update_template PUT /org/admin/templates/:id/admin_update(.:format) templates#admin_update - - - # GET /org/admin/templates/:id/admin_index (admin_index_template_path) the :id here makes no sense! - # ---------------------------------------------------------- - test "get the list of admin templates" do + test "unauthorized user cannot access the templates page" do # Should redirect user to the root path if they are not logged in! - get admin_index_template_path(@user.org) + get org_admin_templates_path assert_unauthorized_redirect_to_root_path - + # Non Org-Admin cannot perform this action + sign_in @regular_user + get org_admin_templates_path + assert_authorized_redirect_to_plans_page + end + + test "Org Admin should see the list of their templates and customizable funder templates" do sign_in @user - - get admin_index_template_path(@user.org) + get org_admin_templates_path assert_response :success - - assert assigns(:funder_templates) - assert assigns(:org_templates) + assert_select "#organisation-templates table tbody tr", @user.org.templates.length, "expected the Org Admin to only see their own templates" + end + + test "Super Admin should see the list of all templates" do + user = User.find_by(email: 'super_admin@example.com') + sign_in user + get org_admin_templates_path + assert_response :success + assert_select "#organisation-templates table tbody tr", Template.where(org: Org.not_funder).pluck(:dmptemplate_id).uniq.length, "expected the Super Admin to see all of the templates" end - # GET /org/admin/templates/:id/admin_template (admin_template_template_path) - # ---------------------------------------------------------- - test "get the admin template" do + test "unauthorized user cannot access the template edit page" do # Should redirect user to the root path if they are not logged in! - get admin_template_template_path(@template) + get edit_org_admin_template_path(@template) assert_unauthorized_redirect_to_root_path + # Non Org-Admin cannot perform this action + sign_in @regular_user + get edit_org_admin_template_path(@template) + assert_authorized_redirect_to_plans_page + end + test "get the template edit page" do sign_in @user - get admin_template_template_path(@template) + get edit_org_admin_template_path(@template) assert_response :success assert assigns(:template) @@ -71,30 +59,37 @@ assert assigns(:current) end -# TODO: Why are we passing an :id here!? Its a new record but we seem to need the last template's id - # GET /org/admin/templates/:id/admin_new (admin_new_template_path) - # ---------------------------------------------------------- - test "get the new admin template page" do + test "unauthorized user cannot access the new template page" do # Should redirect user to the root path if they are not logged in! - get admin_new_template_path(Template.last.id) + get new_org_admin_template_path(Template.last.id) assert_unauthorized_redirect_to_root_path - + # Non Org-Admin cannot perform this action + sign_in @regular_user + get new_org_admin_template_path(Template.last.id) + assert_authorized_redirect_to_plans_page + end + + test "get the new template page" do sign_in @user - get admin_new_template_path(Template.last.id) + get new_org_admin_template_path(Template.last.id) assert_response :success end - # GET /org/admin/templates/:id/admin_template_history (admin_template_history_template_path) - # ---------------------------------------------------------- - test "get the admin template history page" do + test "unauthorized user cannot access the template history page" do # Should redirect user to the root path if they are not logged in! - get admin_template_history_template_path(@template) + get history_org_admin_template_path(@template) assert_unauthorized_redirect_to_root_path - + # Non Org-Admin cannot perform this action + sign_in @regular_user + get history_org_admin_template_path(@template) + assert_authorized_redirect_to_plans_page + end + + test "get the template history page" do sign_in @user - get admin_template_history_template_path(@template) + get history_org_admin_template_path(@template) assert_response :success assert assigns(:template) @@ -102,14 +97,18 @@ assert assigns(:current) end - # DELETE /org/admin/templates/:id/admin_destroy (admin_destroy_template_path) - # ---------------------------------------------------------- + test "unauthorized user cannot delete a template" do + # Should redirect user to the root path if they are not logged in! + delete org_admin_template_path(@template) + assert_unauthorized_redirect_to_root_path + # Non Org-Admin cannot perform this action + sign_in @regular_user + delete org_admin_template_path(@template) + assert_authorized_redirect_to_plans_page + end + test "delete the admin template" do id = @template.id - # Should redirect user to the root path if they are not logged in! - delete admin_destroy_template_path(@template) - assert_unauthorized_redirect_to_root_path - sign_in @user family = @template.dmptemplate_id @@ -120,60 +119,65 @@ current = Template.current(family) # Try to delete a historical version should fail - delete admin_destroy_template_path(prior) + delete org_admin_template_path(prior) assert_equal _('You cannot delete historical versions of this template.'), flash[:alert] assert_response :redirect - assert_redirected_to admin_index_template_path + assert_redirected_to org_admin_templates_path assert_not Template.find(prior.id).nil? # Try to delete the current version should work - delete admin_destroy_template_path(current) + delete org_admin_template_path(current) assert_response :redirect - assert_redirected_to admin_index_template_path + assert_redirected_to org_admin_templates_path assert_raise ActiveRecord::RecordNotFound do Template.find(current.id).nil? end assert_equal prior, Template.current(family), "expected the old version to now be the current version" + + # Should not be able to delete a template that has plans! end -# TODO: Why are we passing an :id here!? Its a new record but we seem to need the last template's id - # POST /org/admin/templates/:id/admin_create (admin_create_template_path) - # ---------------------------------------------------------- + test "unauthorized user cannot create a template" do + # Should redirect user to the root path if they are not logged in! + post org_admin_templates_path(@user.org), {template: {title: ''}} + assert_unauthorized_redirect_to_root_path + # Non Org-Admin cannot perform this action + sign_in @regular_user + post org_admin_templates_path(@user.org), {template: {title: ''}} + assert_authorized_redirect_to_plans_page + end + test "create a template" do params = {title: 'Testing create route'} - - # Should redirect user to the root path if they are not logged in! - post admin_create_template_path(@user.org), {template: params} - assert_unauthorized_redirect_to_root_path - sign_in @user - post admin_create_template_path(@user.org), {template: params} + post org_admin_templates_path(@user.org), {template: params} assert flash[:notice].start_with?('Successfully') && flash[:notice].include?('created') assert_response :redirect - assert_redirected_to admin_template_template_url(Template.last.id) + assert_redirected_to edit_org_admin_template_url(Template.last.id) assert assigns(:template) assert_equal 'Testing create route', Template.last.title, "expected the record to have been created!" # Invalid object - post admin_create_template_path(@user.org), {template: {title: nil, org_id: @user.org.id}} + post org_admin_templates_path(@user.org), {template: {title: nil, org_id: @user.org.id}} assert flash[:alert].starts_with?(_('Could not create your')) assert_response :success assert assigns(:template) assert assigns(:hash) end - - # GET /org/admin/templates/:id/admin_update (admin_update_template_path) - # ---------------------------------------------------------- - test "update the admin template" do - params = {title: 'ABCD'} - + + test "unauthorized user cannot update a template" do # Should redirect user to the root path if they are not logged in! - #get admin_template_template_path(@template) # Click on 'edit' - #@template = Template.current(@template.dmptemplate_id) # Edit working copy - put admin_update_template_path(@template), {template: params} + put org_admin_template_path(@template), {template: {title: ''}} assert_unauthorized_redirect_to_root_path + # Non Org-Admin cannot perform this action + sign_in @regular_user + put org_admin_template_path(@template), {template: {title: ''}} + assert_authorized_redirect_to_plans_page + end + test "update the template" do + params = {title: 'ABCD'} sign_in @user family = @template.dmptemplate_id @@ -184,56 +188,60 @@ current = Template.current(family) # We shouldn't be able to edit a historical version - put admin_update_template_path(prior), {template: params} + put org_admin_template_path(prior), {template: params} assert_equal _('You can not edit a historical version of this template.'), flash[:notice] assert_response :redirect - assert_redirected_to admin_template_template_url(prior) + assert_redirected_to edit_org_admin_template_url(prior) assert assigns(:template) # Make sure we get the right response when editing an unpublished template - put admin_update_template_path(current), {template: params} + put org_admin_template_path(current), {template: params} assert flash[:notice].start_with?('Successfully') && flash[:notice].include?('saved') assert_response :redirect - assert_redirected_to admin_template_template_path + assert_redirected_to edit_org_admin_template_url(current) assert assigns(:template) #assert assigns(:template_hash) assert_equal 'ABCD', current.reload.title, "expected the record to have been updated" assert current.reload.dirty? # Make sure we get the right response when providing an invalid template - put admin_update_template_path(current), {template: {title: nil}} + put org_admin_template_path(current), {template: {title: nil}} assert flash[:alert].starts_with?(_('Could not update your')) assert_response :redirect assert assigns(:template) end - # GET /org/admin/templates/:id/admin_customize (admin_customize_template_path) - # ---------------------------------------------------------- - test "customize a funder template" do + test "unauthorized user cannot customize a template" do # Make sure we are redirected if we're not logged in - get admin_customize_template_path(@template) + get customize_org_admin_template_path(@template) assert_unauthorized_redirect_to_root_path - - funder_template = Template.create(org: Org.funders.first, title: 'Testing integration') + # Non Org-Admin cannot perform this action + sign_in @regular_user + get customize_org_admin_template_path(@template) + assert_authorized_redirect_to_plans_page + end + + test "customize a funder template" do + funder_template = Template.create(org: Org.funder.first, title: 'Testing integration') # Sign in as the funder so that we cna publish the template sign_in User.find_by(org: funder_template.org) - put admin_publish_template_path(funder_template) + get publish_org_admin_template_path(funder_template) assert_response :redirect - assert_redirected_to admin_index_template_path(funder_template.org) + assert_redirected_to org_admin_templates_path # Sign in as the regular user so we can customize the funder template sign_in @user template = Template.live(funder_template.dmptemplate_id) - get admin_customize_template_path(template) + get customize_org_admin_template_path(template) customization = Template.where(customization_of: template.dmptemplate_id).last assert_response :redirect - assert_redirected_to admin_template_template_url(Template.last) + assert_redirected_to edit_org_admin_template_url(Template.last) assert assigns(:template) assert_equal 0, customization.version @@ -252,13 +260,17 @@ end end - # GET /org/admin/templates/:id/admin_publish (admin_publish_template_path) - # ---------------------------------------------------------- - test "publish a template" do + test "unauthorized user cannot publish a template" do # Should redirect user to the root path if they are not logged in! - put admin_publish_template_path(@template) + get publish_org_admin_template_path(@template) assert_unauthorized_redirect_to_root_path - + # Non Org-Admin cannot perform this action + sign_in @regular_user + get publish_org_admin_template_path(@template) + assert_authorized_redirect_to_plans_page + end + + test "publish a template" do sign_in @user family = @template.dmptemplate_id @@ -269,23 +281,23 @@ current = Template.current(family) # We shouldn't be able to edit a historical version - put admin_publish_template_path(prior) + get publish_org_admin_template_path(prior) assert_equal _('You can not publish a historical version of this template.'), flash[:alert] assert_response :redirect - assert_redirected_to admin_template_template_url(prior) + assert_redirected_to org_admin_templates_path assert assigns(:template) # Publish the current template - put admin_publish_template_path(current) + get publish_org_admin_template_path(current) assert_equal _('Your template has been published and is now available to users.'), flash[:notice] assert_response :redirect - assert_redirected_to admin_index_template_path(@user.org) + assert_redirected_to org_admin_templates_path current = Template.current(family) # Update the description so that the template gets versioned - get admin_template_template_path(current) # Click on 'edit' + get edit_org_admin_template_path(current) # Click on 'edit' new_version = Template.current(family) # Edit working copy - put admin_update_template_path(new_version), {template: {description: "this is an update"}} + put org_admin_template_path(new_version), {template: {description: "this is an update"}} # Make sure it versioned properly new_version = Template.current(family) @@ -298,13 +310,17 @@ assert_equal current.dmptemplate_id, new_version.dmptemplate_id, "expected the old and new versions to share the same dmptemplate_id" end - # GET /org/admin/templates/:id/admin_unpublish (admin_unpublish_template_path) - # ---------------------------------------------------------- - test "unpublish a template" do + test "unauthorized user cannot unpublish a template" do # Should redirect user to the root path if they are not logged in! - put admin_unpublish_template_path(@template) + get unpublish_org_admin_template_path(@template) assert_unauthorized_redirect_to_root_path - + # Non Org-Admin cannot perform this action + sign_in @regular_user + get unpublish_org_admin_template_path(@template) + assert_authorized_redirect_to_plans_page + end + + test "unpublish a template" do sign_in @user family = @template.dmptemplate_id @@ -315,15 +331,46 @@ current = Template.current(family) # Publish it so we can unpublish - put admin_publish_template_path(current) + get publish_org_admin_template_path(current) assert_not Template.live(family).nil? - put admin_unpublish_template_path(current) + get unpublish_org_admin_template_path(current) assert_equal _('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] assert_response :redirect - assert_redirected_to admin_index_template_path(@user.org) + assert_redirected_to org_admin_templates_path # Make sure there are no published versions assert Template.live(family).nil? end + + test "unauthorized user cannot copy a template" do + # Should redirect user to the root path if they are not logged in! + get copy_org_admin_template_path(@template) + assert_unauthorized_redirect_to_root_path + # Non Org-Admin cannot perform this action + sign_in @regular_user + get copy_org_admin_template_path(@template) + assert_authorized_redirect_to_plans_page + end + + test "copy a template" do + sign_in @user + get copy_org_admin_template_path(@template) + assert_response :redirect + assert_redirected_to "#{edit_org_admin_template_url(Template.last)}?edit=true" + end + + test "unauthorized user cannot transfer a template customization" do + # Should redirect user to the root path if they are not logged in! + get transfer_customization_org_admin_template_path(@template) + assert_unauthorized_redirect_to_root_path + # Non Org-Admin cannot perform this action + sign_in @regular_user + get transfer_customization_org_admin_template_path(@template) + assert_authorized_redirect_to_plans_page + end + + test "transfer a template customization" do + # TODO add test for this. Could not get working, getting a nil for max_version within the method (NOT SURE IF THIS IS STILL IN USE!) + end end diff --git a/test/integration/template_selection_test.rb b/test/integration/template_selection_test.rb index d3aff01..a9b61d0 100644 --- a/test/integration/template_selection_test.rb +++ b/test/integration/template_selection_test.rb @@ -8,7 +8,6 @@ @template = Template.default @researcher = User.last - scaffold_org_admin(@template.org) @funder = Org.find_by(org_type: 2) @@ -31,7 +30,7 @@ sign_in @researcher - get "#{template_options_template_path(@researcher)}?plan[org_id]=#{@template.org_id}" + get "#{org_admin_template_options_path}?plan[org_id]=#{@template.org_id}" assert_response :success json = JSON.parse(@response.body) @@ -44,7 +43,7 @@ template = version_template(template) # Make sure the published version is used - get "#{template_options_template_path(@researcher)}?plan[org_id]=#{@template.org_id}" + get "#{org_admin_template_options_path}?plan[org_id]=#{@template.org_id}" assert_response :success json = JSON.parse(@response.body) @@ -54,11 +53,11 @@ # Update the template and make sure the published version stayed the same sign_in @user - put admin_update_template_path(template), {template: {title: "Blah blah blah"}} + put org_admin_template_path(template), {template: {title: "Blah blah blah"}} sign_in @researcher - get "#{template_options_template_path(@researcher)}?plan[org_id]=#{@template.org_id}" + get "#{org_admin_template_options_path}?plan[org_id]=#{@template.org_id}" assert_response :success json = JSON.parse(@response.body) @@ -77,7 +76,7 @@ end sign_in @researcher - get "#{template_options_template_path(@researcher)}?plan[org_id]=" + get "#{org_admin_template_options_path}?plan[org_id]=" assert_response :success json = JSON.parse(@response.body) @@ -88,7 +87,7 @@ # ---------------------------------------------------------- test 'plan gets org template when no funder' do sign_in @researcher - get "#{template_options_template_path(@researcher)}?plan[org_id]=#{@org.id}&plan[funder_id]=" + get "#{org_admin_template_options_path}?plan[org_id]=#{@org.id}&plan[funder_id]=" assert_response :success json = JSON.parse(@response.body) @@ -100,7 +99,7 @@ # ---------------------------------------------------------- test 'plan gets funder template when no org' do sign_in @researcher - get "#{template_options_template_path(@researcher)}?plan[org_id]=&plan[funder_id]=#{@funder.id}" + get "#{org_admin_template_options_path}?plan[org_id]=&plan[funder_id]=#{@funder.id}" assert_response :success json = JSON.parse(@response.body) @@ -113,7 +112,7 @@ test 'plan gets funder template when org has no customization' do sign_in @researcher - get "#{template_options_template_path(@researcher)}?plan[org_id]=#{@org.id}&plan[funder_id]=#{@funder.id}" + get "#{org_admin_template_options_path}?plan[org_id]=#{@org.id}&plan[funder_id]=#{@funder.id}" assert_response :success json = JSON.parse(@response.body) @@ -131,7 +130,7 @@ sign_in @researcher - get "#{template_options_template_path(@researcher)}?plan[org_id]=#{@org.id}&plan[funder_id]=#{@funder.id}" + get "#{org_admin_template_options_path}?plan[org_id]=#{@org.id}&plan[funder_id]=#{@funder.id}" assert_response :success json = JSON.parse(@response.body) @@ -148,7 +147,7 @@ sign_in @researcher - get "#{template_options_template_path(@researcher)}?plan[org_id]=#{@org.id}&plan[funder_id]=#{@funder.id}" + get "#{org_admin_template_options_path}?plan[org_id]=#{@org.id}&plan[funder_id]=#{@funder.id}" assert_response :success json = JSON.parse(@response.body) @@ -161,7 +160,7 @@ private # ---------------------------------------------------------- def version_template(template) - put admin_publish_template_path(template) + get publish_org_admin_template_path(template) Template.current(template.dmptemplate_id) end end diff --git a/test/integration/template_versioning_test.rb b/test/integration/template_versioning_test.rb index dd59836..95a2d4d 100644 --- a/test/integration/template_versioning_test.rb +++ b/test/integration/template_versioning_test.rb @@ -22,13 +22,13 @@ # ---------------------------------------------------------- test 'template gets versioned when its details are updated but it is already published' do # Publish the template - put admin_publish_template_path(@template) + get publish_org_admin_template_path(@template) @template = Template.current(@dmptemplate_id) - get admin_template_template_path(@template) # Click on 'edit' + get edit_org_admin_template_path(@template) # Click on 'edit' @template = Template.current(@dmptemplate_id) # Edit new version # Change the title after its been published - put admin_update_template_path(@template), {template: {title: "Blah blah blah"}} + put org_admin_template_path(@template), {template: {title: "Blah blah blah"}} @template = Template.current(@dmptemplate_id) # Make sure that the template was versioned @@ -78,7 +78,7 @@ # ---------------------------------------------------------- test 'template does NOT get versioned if its unpublished' do # Change the title after its been published - put admin_update_template_path(@template), {template: {title: "Blah blah blah"}} + put org_admin_template_path(@template), {template: {title: "Blah blah blah"}} @template = Template.current(@dmptemplate_id) assert_equal @initial_version, @template.version, "expected the version to have stayed the same" @@ -89,15 +89,15 @@ # ---------------------------------------------------------- test 'publishing a plan unpublishes the old published plan' do - put admin_publish_template_path(@template) + get publish_org_admin_template_path(@template) assert_not Template.live(@dmptemplate_id).nil? assert_equal 1, Template.where(org: @user.org, dmptemplate_id: @dmptemplate_id, published: true).count end # ---------------------------------------------------------- test 'unpublishing a plan makes all historical versions unpublished' do - put admin_publish_template_path(@template) - put admin_unpublish_template_path(@template) + get publish_org_admin_template_path(@template) + get unpublish_org_admin_template_path(@template) assert Template.live(@dmptemplate_id).nil? end diff --git a/test/test_helper.rb b/test/test_helper.rb index 1d8928e..de382d3 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -87,10 +87,10 @@ # Version the template # ---------------------------------------------------------------------- def version_the_template - put admin_publish_template_path(@template) - get admin_template_template_path(@template) # Click on 'edit' + get publish_org_admin_template_path(@template) + get edit_org_admin_template_path(@template) # Click on 'edit' @template = Template.current(@template.dmptemplate_id) # Edit working copy - put admin_update_template_path(@template), {template: {title: "#{@template.title} - VERSIONED"}} + put org_admin_template_path(@template), {template: {title: "#{@template.title} - VERSIONED"}} end # Scaffold a new Plan based on the scaffolded Template diff --git a/test/unit/guidance_group_test.rb b/test/unit/guidance_group_test.rb index bbb2e3e..542bf46 100644 --- a/test/unit/guidance_group_test.rb +++ b/test/unit/guidance_group_test.rb @@ -46,7 +46,7 @@ # --------------------------------------------------- test "user can view guidance_group if it belongs to a funder" do - gg = GuidanceGroup.create(name: 'Funder Test', org: Org.funders.first) + gg = GuidanceGroup.create(name: 'Funder Test', org: Org.funder.first) assert GuidanceGroup.can_view?(@user, gg) end @@ -66,7 +66,7 @@ ggs = [@guidance_group, GuidanceGroup.create(name: 'User Test', org: @org), - GuidanceGroup.create(name: 'Funder Test', org: Org.funders.first), + GuidanceGroup.create(name: 'Funder Test', org: Org.funder.first), GuidanceGroup.create(name: 'Managing CC Test', org: Org.managing_orgs.first)] v = GuidanceGroup.all_viewable(@user) diff --git a/test/unit/guidance_test.rb b/test/unit/guidance_test.rb index 7812a86..9ef04bf 100644 --- a/test/unit/guidance_test.rb +++ b/test/unit/guidance_test.rb @@ -54,7 +54,7 @@ @guidance_group.save! assert Guidance.can_view?(@user, @guidance.id), "expected the user to be able to view guidance belonging to the managing org" - @guidance_group.org = Org.funders.first + @guidance_group.org = Org.funder.first @guidance_group.save! assert Guidance.can_view?(@user, @guidance.id), "expected the user to be able to view guidance belonging to a funder" end @@ -66,13 +66,13 @@ assert viewable.include?(@guidance), "expected the user to be able to view guidance belonging to their org" GuidanceGroup.create(name: 'managing guidance group test', org: Org.managing_orgs.first) - GuidanceGroup.create(name: 'funder guidance group test', org: Org.funders.first) + GuidanceGroup.create(name: 'funder guidance group test', org: Org.funder.first) Org.managing_orgs.first.guidance_groups.first.guidances.each do |g| assert viewable.include?(g), "expected the user to be able to view all managing org guidance" end - Org.funders.first.guidance_groups.first.guidances.each do |g| + Org.funder.first.guidance_groups.first.guidances.each do |g| assert viewable.include?(g), "expected the user to be able to view all funder guidance" end end