diff --git a/app/controllers/plans_controller.rb b/app/controllers/plans_controller.rb index 1dc970a363..476c6cc389 100644 --- a/app/controllers/plans_controller.rb +++ b/app/controllers/plans_controller.rb @@ -2,19 +2,13 @@ class PlansController < ApplicationController require 'pp' helper SettingsTemplateHelper - after_action :verify_authorized, except: ['public_index'] + after_action :verify_authorized def index authorize Plan @plans = current_user.active_plans end - # GET /plans/public_index - # ------------------------------------------------------------------------------------ - def public_index - @plans = Plan.publicly_visible - end - # GET /plans/new # ------------------------------------------------------------------------------------ def new @@ -38,13 +32,13 @@ def new def create @plan = Plan.new authorize @plan - + @plan.principal_investigator = current_user.surname.blank? ? nil : "#{current_user.firstname} #{current_user.surname}" @plan.principal_investigator_email = current_user.email - + orcid = current_user.identifier_for(IdentifierScheme.find_by(name: 'orcid')) @plan.principal_investigator_identifier = orcid.identifier unless orcid.nil? - + @plan.funder_name = plan_params[:funder_name] @plan.visibility = (plan_params['visibility'].blank? ? Rails.application.config.default_plan_visibility : @@ -127,7 +121,7 @@ def show @all_guidance_groups = @plan.get_guidance_group_options @all_ggs_grouped_by_org = @all_guidance_groups.sort.group_by(&:org) @selected_guidance_groups = @plan.guidance_groups - + # Important ones come first on the page - we grab the user's org's GGs and "Organisation" org type GGs @important_ggs = [] @important_ggs << [current_user.org, @all_ggs_grouped_by_org.delete(current_user.org)] @@ -136,7 +130,7 @@ def show @important_ggs << [org,ggs] @all_ggs_grouped_by_org.delete(org) end - + # If this is one of the already selected guidance groups its important! if !(ggs & @selected_guidance_groups).empty? @important_ggs << [org,ggs] unless @important_ggs.include?([org,ggs]) @@ -148,7 +142,7 @@ def show @important_ggs = @important_ggs.sort_by{|org,gg| (org.nil? ? '' : org.name)} @all_ggs_grouped_by_org = @all_ggs_grouped_by_org.sort_by {|org,gg| (org.nil? ? '' : org.name)} @selected_guidance_groups = @selected_guidance_groups.collect{|gg| gg.id} - + @based_on = (@plan.template.customization_of.nil? ? @plan.template : Template.where(dmptemplate: @plan.template.customization_of).first) respond_to :html @@ -175,7 +169,7 @@ def update end end end - + def share @plan = Plan.find(params[:id]) authorize @plan @@ -288,50 +282,6 @@ def export end end - # GET /plans/[:plan_slug]/public_export - # ------------------------------------------------------------- - def public_export - @plan = Plan.find(params[:id]) - authorize @plan - # If the plan has multiple phases we should export each - @exported_plan = ExportedPlan.new.tap do |ep| - ep.plan = @plan - ep.phase_id = @plan.phases.first.id - ep.format = :pdf - plan_settings = @plan.settings(:export) - - Settings::Template::DEFAULT_SETTINGS.each do |key, value| - ep.settings(:export).send("#{key}=", plan_settings.send(key)) - end - end - # need to determine which phases to export - @a_q_ids = Answer.where(plan_id: @plan.id).pluck(:question_id).uniq - @a_s_ids = Question.where(id: @a_q_ids).pluck(:section_id).uniq - a_p_ids = Section.where(id: @a_s_ids).pluck(:phase_id).uniq - @phases = Phase.includes(sections: :questions).where(id: a_p_ids).order(:number) - - begin - @exported_plan.save! - file_name = @plan.title.gsub(/ /, "_") - - respond_to do |format| - format.pdf do - @formatting = @plan.settings(:export).formatting - render pdf: file_name, - margin: @formatting[:margin], - footer: { - center: _('This document was generated by %{application_name}') % {application_name: Rails.configuration.branding[:application][:name]}, - font_size: 8, - spacing: (@formatting[:margin][:bottom] / 2) - 4, - right: '[page] of [topage]' - } - end - end - rescue ActiveRecord::RecordInvalid => e - @phase_options = @plan.phases.order(:number).pluck(:title,:id) - redirect_to show_export_plan_path(@plan), alert: _('Unable to download the DMP at this time.') - end - end def duplicate plan = Plan.find(params[:id]) @@ -350,7 +300,7 @@ def duplicate end end end - + # AJAX access to update the plan's visibility # POST /plans/:id def visibility @@ -363,7 +313,7 @@ def visibility render status: :bad_request, json: {msg: _("Unable to change the plan's status")} end end - + def set_test plan = Plan.find(params[:id]) authorize plan @@ -374,7 +324,7 @@ def set_test render status: :bad_request, json: {msg: _("Unable to change the plan's test status")} end end - + private @@ -403,7 +353,7 @@ def save_guidance_selections(guidance_group_ids) end @plan.save end - + # different versions of the same template have the same dmptemplate_id # but different version numbers so for each set of templates with the diff --git a/app/controllers/public_pages_controller.rb b/app/controllers/public_pages_controller.rb new file mode 100644 index 0000000000..63513c652c --- /dev/null +++ b/app/controllers/public_pages_controller.rb @@ -0,0 +1,125 @@ +class PublicPagesController < ApplicationController + after_action :verify_authorized + + # GET template_index + # ----------------------------------------------------- + def template_index + authorize :public_page + template_ids = Template.where(org_id: Org.funders.pluck(:id)).valid.pluck(:dmptemplate_id).uniq << Template.where(is_default: true).pluck(:dmptemplate_id) + @templates = [] + template_ids.each do |tid| + t = Template.live(tid) + @templates << t unless t.nil? + end + end + + # GET template_export/:id + # ----------------------------------------------------- + def template_export + # only export live templates, id passed is dmptemplate_id + @template = Template.live(params[:id]) + # covers authorization for this action. Pundit dosent support passing objects into scoped policies + raise Pundit::NotAuthorizedError unless PublicPagePolicy.new( @template).template_export? + skip_authorization + # now with prefetching (if guidance is added, prefetch annottaions/guidance) + @template = Template.includes(:org, phases: {sections:{questions:[:question_options, :question_format]}}).find(@template.id) + + begin + file_name = @template.title.gsub(/ /, "_") + respond_to do |format| + format.docx { render docx: 'template_export', filename: "#{file_name}.docx" } + format.pdf do + @formatting = Settings::Template::DEFAULT_SETTINGS[:formatting] + render pdf: file_name, + margin: @formatting[:margin], + footer: { + center: _('This document was generated by %{application_name}') % {application_name: Rails.configuration.branding[:application][:name]}, + font_size: 8, + spacing: (@formatting[:margin][:bottom] / 2) - 4, + right: '[page] of [topage]' + } + end + end + rescue ActiveRecord::RecordInvalid => e # What scenario is this triggered in? it's common to our export pages + #send back to public_index page + redirect_to template_index_path, alert: _('Unable to download the DMP Template at this time.') + end + + end + + # GET plan_export/:id + # ------------------------------------------------------------- + def plan_export + @plan = Plan.find(params[:id]) + # covers authorization for this action. Pundit dosent support passing objects into scoped policies + raise Pundit::NotAuthorizedError unless PublicPagePolicy.new( @plan).plan_export? + skip_authorization + # This creates exported_plans with no user. + # Note for reviewers, The ExportedPlan model actually serves no purpose, except + # to store preferences for PDF export. These preferences could be moved into + # the prefs table for individual users, and a more semsible structure implimented + # to track the exports & formats(html/pdf/ect) of users. + @exported_plan = ExportedPlan.new.tap do |ep| + ep.plan = @plan + ep.phase_id = @plan.phases.first.id + ep.format = :pdf + plan_settings = @plan.settings(:export) + + Settings::Template::DEFAULT_SETTINGS.each do |key, value| + ep.settings(:export).send("#{key}=", plan_settings.send(key)) + end + end + # need to determine which phases to export + @a_q_ids = Answer.where(plan_id: @plan.id).pluck(:question_id).uniq + @a_s_ids = Question.where(id: @a_q_ids).pluck(:section_id).uniq + a_p_ids = Section.where(id: @a_s_ids).pluck(:phase_id).uniq + @phases = Phase.includes(sections: :questions).where(id: a_p_ids).order(:number) + # name of owner and any co-owners + @creator_text = @plan.owner.name(false) + @plan.roles.administrator.not_creator.each do |co_owner| + @creator_text += ", " + co_owner.name(false) + end + # Org name of plan owner + @affiliation = @plan.owner.org.name + # set the funder name + @funder = @plan.template.org.funder? ? @plan.template.org.name : nil + # set the template name and customizer name if applicable + @template = @plan.template.title + @customizer = "" + cust_questions = @plan.questions.where(modifiable: true).pluck(:id) + # if the template is customized, and has custom answered questions + if @plan.template.customization_of.present? && Answer.where(plan_id: @plan.id, question_id: cust_questions).present? + @customizer = _(" Customised By: ") + @plan.template.org.name + end + + + begin + @exported_plan.save! + file_name = @plan.title.gsub(/ /, "_") + + respond_to do |format| + format.pdf do + @formatting = @plan.settings(:export).formatting + render pdf: file_name, + margin: @formatting[:margin], + footer: { + center: _('This document was generated by %{application_name}') % {application_name: Rails.configuration.branding[:application][:name]}, + font_size: 8, + spacing: (@formatting[:margin][:bottom] / 2) - 4, + right: '[page] of [topage]' + } + end + end + rescue ActiveRecord::RecordInvalid => e + # send to the public_index page + redirect_to public_index_plan_path, alert: _('Unable to download the DMP at this time.') + end + end + + # GET /plans_index + # ------------------------------------------------------------------------------------ + def plan_index + authorize :public_page + @plans = Plan.publicly_visible + end +end diff --git a/app/controllers/templates_controller.rb b/app/controllers/templates_controller.rb index c20380f9c6..4001bbeb1a 100644 --- a/app/controllers/templates_controller.rb +++ b/app/controllers/templates_controller.rb @@ -3,7 +3,7 @@ # [+Copyright:+] Digital Curation Centre and University of California Curation Center class TemplatesController < ApplicationController - respond_to :html + #respond_to :html after_action :verify_authorized # GET /org/admin/templates/:id/admin_index diff --git a/app/policies/plan_policy.rb b/app/policies/plan_policy.rb index 22fd1f9957..762b0b7234 100644 --- a/app/policies/plan_policy.rb +++ b/app/policies/plan_policy.rb @@ -43,7 +43,7 @@ def possible_templates? def duplicate? @plan.editable_by?(@user.id) && Role.find_by(user_id: @user.id, plan_id: @plan.id).active end - + def visibility? @plan.administerable_by?(@user.id) && Role.find_by(user_id: @user.id, plan_id: @plan.id).active end @@ -52,10 +52,6 @@ def set_test? @plan.administerable_by?(@user.id)&& Role.find_by(user_id: @user.id, plan_id: @plan.id).active end - def public_export? - @plan.publicly_visible? - end - def answer? @plan.readable_by?(@user.id) && Role.find_by(user_id: @user.id, plan_id: @plan.id).active end diff --git a/app/policies/public_page_policy.rb b/app/policies/public_page_policy.rb new file mode 100644 index 0000000000..e4b237b0a7 --- /dev/null +++ b/app/policies/public_page_policy.rb @@ -0,0 +1,24 @@ +class PublicPagePolicy < ApplicationPolicy + + def initialize( object) + # no requirement for users to be signed in here + @object = object + end + + def plan_index? + true + end + + def template_index? + true + end + + def template_export? + @object.is_default || @object.org.funder? + end + + def plan_export? + @object.publicly_visible? + end + +end diff --git a/app/policies/template_policy.rb b/app/policies/template_policy.rb index 006ed23170..feb94b6414 100644 --- a/app/policies/template_policy.rb +++ b/app/policies/template_policy.rb @@ -20,15 +20,15 @@ def admin_index? 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 diff --git a/app/views/layouts/_navigation.html.erb b/app/views/layouts/_navigation.html.erb index 718f023a09..04d047e5f3 100644 --- a/app/views/layouts/_navigation.html.erb +++ b/app/views/layouts/_navigation.html.erb @@ -1,5 +1,5 @@ - + <% if user_signed_in? %> - + <% if current_user.can_org_admin? && action_name.include?("admin_") %> <% if current_user.can_modify_templates? %> @@ -31,7 +34,7 @@ <% end %> <% if current_user.can_modify_org_details? %>
  • > - <%= link_to _('Organisation details'), admin_edit_org_path(current_user.org_id) %> + <%= link_to _('Organisation details'), admin_edit_org_path(current_user.org_id) %>
  • <% end %> <% if current_user.can_grant_permissions? %> @@ -55,10 +58,10 @@ <%= link_to _('My Dashboard'), plans_path %> - <% + <% if current_user.can_org_admin? && !current_user.org_id.nil? && !action_name.include?("admin_") link = nil - + if current_user.can_modify_org_details? && current_user.org.abbreviation.blank? link = admin_edit_org_path(current_user.org_id) elsif current_user.can_modify_templates? @@ -78,4 +81,4 @@ <% end %> <% end %> - \ No newline at end of file + diff --git a/app/views/plans/public_export.pdf.erb b/app/views/public_pages/plan_export.pdf.erb similarity index 77% rename from app/views/plans/public_export.pdf.erb rename to app/views/public_pages/plan_export.pdf.erb index ca7fb8312d..af374d6077 100644 --- a/app/views/plans/public_export.pdf.erb +++ b/app/views/public_pages/plan_export.pdf.erb @@ -18,11 +18,29 @@ -

    <%= @plan.title %>

    +
    +

    <%= @plan.title %>

    +

    <%= _("A Data Management Plan created using ") + Rails.configuration.branding[:application][:name] + "." %>

    +
    +
    +

    <%= _("Creator(s): ") + @creator_text %>


    +

    <%= _("Affiliation: ") + @affiliation %>


    + <% if @funder.present? %> +

    <%= _("Funder: ") + @funder %>


    + <% else %> +

    <%= _("Template: ") + @template + @customizer %>


    + <% end %> + <% if @plan.grant_number.present? %> +

    <%= _("Grant Number: ") + @plan.grant_number %>


    + <% end %> + <% if @plan.description.present? %> +

    <%= _("Description: ") + @plan.description %>


    + <% end %> +

    <%= _("Last Updated: ") + @plan.updated_at.to_date.to_s %>


    <%= _("Copyright information: The above plan creator(s) have agreed that others may use as much of the text of this plan as they would like in their own plans, and customise it as necessary. You do not need to credit the creator(s) as the source of the language used, but using any of the plan's text does not imply that the creator(s) endorse, or have any relationship to, your project or proposal") %>

    <% @phases.each do |phase| %> -
    +

    <%= phase.title %>

    <% Section.where(phase_id: phase.id, id: @a_s_ids).order(:number).each do |section| %>

    <%= section.title %>

    @@ -58,4 +76,4 @@ <% end %> <% end %> - \ No newline at end of file + diff --git a/app/views/plans/public_index.html.erb b/app/views/public_pages/plan_index.html.erb similarity index 89% rename from app/views/plans/public_index.html.erb rename to app/views/public_pages/plan_index.html.erb index 5f0fdaeb4e..b3353fbcb1 100644 --- a/app/views/plans/public_index.html.erb +++ b/app/views/public_pages/plan_index.html.erb @@ -15,14 +15,14 @@

    <% end %> -<% if @plans.count > 0 %> +<% if @plans.count > 0 %>
    <% if @plans.count > 10 %> @@ -43,8 +43,8 @@ @@ -52,4 +52,4 @@
    - <%= render(partial: "shared/table_filter", + <%= render(partial: "shared/table_filter", locals: {path: public_plans_path, placeholder: _('Filter plans')}) %>
    <%= (plan.owner.nil? || plan.owner.org.nil? ? _('Not Applicable') : plan.owner.org.name) %> <%= (plan.owner.nil? ? _('Unknown') : plan.owner.name(false)) %> - <%= link_to _('PDF'), - public_export_path(plan, format: :pdf), + <%= link_to _('PDF'), + plan_export_path(plan, format: :pdf), class: "dmp_table_link" %>
    -<% end %> \ No newline at end of file +<% end %> diff --git a/app/views/public_pages/template_export.docx.erb b/app/views/public_pages/template_export.docx.erb new file mode 100644 index 0000000000..b2932b6c72 --- /dev/null +++ b/app/views/public_pages/template_export.docx.erb @@ -0,0 +1,30 @@ +
    +

    <%= @template.title %>

    +

    <%= _("A Data Management Plan created using ") + Rails.configuration.branding[:application][:name] + "." %>

    +
    +

    <%= _("Organisation: ") + @template.org.name %>


    +<% if @template.description.present? %> +

    <%= _("Description: ")%><%= raw(@template.description) %>


    +<% end %> +
    + +<% @template.phases.each do |phase| %> + +
    +

    <%= phase.title %>

    + <% phase.sections.each do |section| %> +

    <%= section.title %>

    + <% section.questions.each do |question|%> +

    <%= raw question.text %>

    + <% q_format = question.question_format %> + <% if q_format.option_based? %> + + <% end %> +
    + <% end %> + <% end %> +<% end %> diff --git a/app/views/public_pages/template_export.pdf.erb b/app/views/public_pages/template_export.pdf.erb new file mode 100644 index 0000000000..3252a603e3 --- /dev/null +++ b/app/views/public_pages/template_export.pdf.erb @@ -0,0 +1,52 @@ + + + + + + <%= @template.title %> + + + + +
    +

    <%= @template.title %>

    +

    <%= _("A Data Management Plan created using ") + Rails.configuration.branding[:application][:name] + "." %>

    +
    +
    +

    <%= _("Organisation: ") + @template.org.name %>


    + <% if @template.description.present? %> +

    <%= _("Description: ")%><%= raw(@template.description) %>

    + <% end %> + + <% @template.phases.each do |phase| %> +
    +

    <%= phase.title %>

    + <% phase.sections.each do |section| %> +

    <%= section.title %>

    + <% section.questions.each do |question| %> +
    +

    <%= raw question.text %>

    + <% q_format = question.question_format %> + <% if q_format.option_based? %> + + <% end %> +
    + <% end %> + <% end %> + <% end %> + + diff --git a/app/views/public_pages/template_index.html.erb b/app/views/public_pages/template_index.html.erb new file mode 100644 index 0000000000..903dcc8e89 --- /dev/null +++ b/app/views/public_pages/template_index.html.erb @@ -0,0 +1,45 @@ +<%- model_class = Template -%> + +

    + <%= raw _('DMP Templates') %> +

    + + +<% if @templates.count > 0 %> +

    <%= _('Templates are provided by a funder, an institution, or a trusted party.') %>

    +<% else %> +

    <%= _('There are currently no public Templates.')%>

    +<% end %> + +<% if @templates.count > 0 %> +
    + + + <% if @templates.count > 10 %> + + + + <% end %> + + + + + + + + <% @templates.each do |template| %> + + + + + + <% end %> +
    + <%= render(partial: "shared/table_filter", + locals: {path: public_templates_path, placeholder: _('Filter templates')}) %> +
    <%= _('Template Name') %><%= _('Organisation Name') %><%= _('Download') %>
    <%= template.title %><%= template.org.name %> + <%= link_to _('DOCX'), template_export_path(template.dmptemplate_id, format: :docx) %> + <%= link_to _('PDF'), template_export_path(template.dmptemplate_id, format: :pdf) %> +
    +
    +<% end %> diff --git a/app/views/templates/export.pdf.erb b/app/views/templates/export.pdf.erb deleted file mode 100644 index 3726b39a6a..0000000000 --- a/app/views/templates/export.pdf.erb +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - <%= @template.title %> - - - - -

    <%= @template.title %>

    - - \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index defb261070..cdc56881bf 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -83,8 +83,10 @@ get "help" => 'static_pages#help' get "roadmap" => 'static_pages#roadmap' get "terms" => 'static_pages#termsuse' - get "public_plans" => 'plans#public_index' - get "public_export/:id" => 'plans#public_export', as: 'public_export' + get "public_plans" => 'public_pages#plan_index' + get "public_templates" => 'public_pages#template_index' + get "template_export/:id" => 'public_pages#template_export', as: 'template_export' + get "plan_export/:id" => 'public_pages#plan_export', as: 'plan_export' get "existing_users" => 'existing_users#index' #post 'contact_form' => 'contacts', as: 'localized_contact_creation'