diff --git a/app/controllers/plans_controller.rb b/app/controllers/plans_controller.rb index ae97316..589b7f8 100644 --- a/app/controllers/plans_controller.rb +++ b/app/controllers/plans_controller.rb @@ -234,58 +234,33 @@ def export - @plan = Plan.find(params[:id]) + @plan = Plan.includes(:answers).joins(:answers).find(params[:id]) authorize @plan - # We should re-work this into something more useful than creating a new one - # every time a plan gets exported - @exported_plan = ExportedPlan.new.tap do |ep| - ep.plan = @plan - ep.phase_id = params[:phase_id] - ep.user = current_user - ep.format = params[:format].to_sym - plan_settings = @plan.settings(:export) + @show_coversheet = params[:export][:project_details].present? + @show_sections_questions = params[:export][:question_headings].present? + @show_unanswered = params[:export][:unanswered_questions].present? - Settings::Template::DEFAULT_SETTINGS.each do |key, value| - ep.settings(:export).send("#{key}=", plan_settings.send(key)) + @hash = @plan.as_pdf(@show_coversheet) + @formatting = @plan.settings(:export).formatting + file_name = @plan.title.gsub(/ /, "_") + + respond_to do |format| + format.html + format.csv { send_data @exported_plan.as_csv(@sections, @unanswered_question, @question_headings), filename: "#{file_name}.csv" } + format.text { send_data @exported_plan.as_txt(@sections, @unanswered_question, @question_headings, @show_details), filename: "#{file_name}.txt" } + format.docx { render docx: 'export', filename: "#{file_name}.docx" } + format.pdf do + render pdf: file_name, + margin: @formatting[:margin], + footer: { + center: _('Created using the %{application_name}. Last modified %{date}') % {application_name: Rails.configuration.branding[:application][:name], date: l(@plan.updated_at.to_date, formats: :short)}, + font_size: 8, + spacing: (@formatting[:margin][:bottom] / 2) - 4, + right: '[page] of [topage]' + } end end - - # setup some variables we will need in the export views - # here, if custom sections are included, we want all sections, otherwise, - # we only want those which are not modifiable, as they are the original template - @sections = params[:export][:custom_sections].present? || @plan.template.customization_of.nil? ? @exported_plan.sections.order(:number) : Phase.find(params[:phase_id]).sections.where(modifiable: false) # prefetch questions? - @unanswered_questions = params[:export][:unanswered_questions].present? - @question_headings = params[:export][:question_headings].present? - @show_details = params[:export][:project_details].present? - - - begin - @exported_plan.save! - file_name = @exported_plan.settings(:export)[:value]['title'].gsub(/ /, "_") - - respond_to do |format| - format.html - format.csv { send_data @exported_plan.as_csv(@sections, @unanswered_question, @question_headings), filename: "#{file_name}.csv" } - format.text { send_data @exported_plan.as_txt(@sections, @unanswered_question, @question_headings, @show_details), filename: "#{file_name}.txt" } - format.docx { render docx: 'export', filename: "#{file_name}.docx" } - format.pdf do - @formatting = @plan.settings(:export).formatting - render pdf: file_name, - margin: @formatting[:margin], - footer: { - center: _('Created using the %{application_name}. Last modified %{date}') % {application_name: Rails.configuration.branding[:application][:name], date: l(@plan.updated_at.to_date, formats: :short)}, - font_size: 8, - spacing: (@formatting[:margin][:bottom] / 2) - 4, - right: '[page] of [topage]' - } - end - end - rescue ActiveRecord::RecordInvalid => e - @phase_options = @plan.phases.order(:number).pluck(:title,:id) - redirect_to download_plan_path(@plan), alert: _('%{format} is not a valid exporting format. Available formats to export are %{available_formats}.') % - {format: params[:format], available_formats: ExportedPlan::VALID_FORMATS.to_s} - end end diff --git a/app/controllers/public_pages_controller.rb b/app/controllers/public_pages_controller.rb index a6ef410..98ffad9 100644 --- a/app/controllers/public_pages_controller.rb +++ b/app/controllers/public_pages_controller.rb @@ -46,69 +46,35 @@ # GET plan_export/:id # ------------------------------------------------------------- def plan_export - @plan = Plan.find(params[:id]) + @plan = Plan.includes(:answers).joins(:answers).find(params[:id]) # covers authorization for this action. Pundit dosent support passing objects into scoped policies raise Pundit::NotAuthorizedError unless PublicPagePolicy.new(@plan, current_user).plan_organisationally_exportable? || 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)) + @show_coversheet = true + @show_sections_questions = true + @show_unanswered = true + + @hash = @plan.as_pdf(@show_coversheet) + @formatting = @plan.settings(:export).formatting + file_name = @plan.title.gsub(/ /, "_") + + respond_to do |format| + format.html + format.csv { send_data @exported_plan.as_csv(@sections, @unanswered_question, @question_headings), filename: "#{file_name}.csv" } + format.text { send_data @exported_plan.as_txt(@sections, @unanswered_question, @question_headings, @show_details), filename: "#{file_name}.txt" } + format.docx { render docx: 'export', filename: "#{file_name}.docx" } + format.pdf do + render pdf: file_name, + margin: @formatting[:margin], + footer: { + center: _('Created using the %{application_name}. Last modified %{date}') % {application_name: Rails.configuration.branding[:application][:name], date: l(@plan.updated_at.to_date, formats: :short)}, + font_size: 8, + spacing: (@formatting[:margin][:bottom] / 2) - 4, + right: '[page] of [topage]' + } 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 |role| - @creator_text += ", " + role.user.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, show_as_html: params.key?('debug'), - footer: { - center: _('Created using the %{application_name}. Last modified %{date}') % {application_name: Rails.configuration.branding[:application][:name], date: l(@plan.updated_at.to_date, formats: :short)}, - font_size: 8, - spacing: (@formatting[:margin][:bottom] / 2) - 12, - right: '[page] of [topage]', - } - end - end - rescue ActiveRecord::RecordInvalid => e - # send to the public_index page - redirect_to public_plans_path, alert: _('Unable to download the DMP at this time.') - end end # GET /plans_index diff --git a/app/models/concerns/exportable_plan.rb b/app/models/concerns/exportable_plan.rb new file mode 100644 index 0000000..d9a3a03 --- /dev/null +++ b/app/models/concerns/exportable_plan.rb @@ -0,0 +1,90 @@ +module ExportablePlan + extend ActiveSupport::Concern + + included do + + def as_pdf(coversheet = false) + prepare(coversheet) + end + + private + def prepare(coversheet = false) + hash = coversheet ? prepare_coversheet : {} + template = Template.includes(phases: { sections: {questions: :question_format } }). + joins(phases: { sections: { questions: :question_format } }). + where(id: self.template_id).first + + hash[:title] = self.title + hash[:answers] = self.answers + + # add the relevant questions/answers + phases = [] + template.phases.each do |phase| + phs = { title: phase.title, number: phase.number, sections: [] } + phase.sections.each do |section| + sctn = { title: section.title, number: section.number, questions: [] } + section.questions.each do |question| + txt = [] + if question.question_format.option_based? + opts = QuestionOption.where(question_id: question.id) + opts.each do |opt| + txt << opt.text + end + else + txt << question.text + end + sctn[:questions] << { id: question.id, text: txt } + end + phs[:sections] << sctn + end + phases << phs + end + hash[:phases] = phases + + record_plan_export(:pdf) + + hash + end + + def prepare_coversheet + hash = {} + # name of owner and any co-owners + attribution = self.owner.present? ? [self.owner.name(false)] : [] + self.roles.administrator.not_creator.each do |role| + attribution << role.user.name(false) + end + hash[:attribution] = attribution + + # Org name of plan owner's org + hash[:affiliation] = self.owner.present? ? self.owner.org.name : '' + + # set the funder name + hash[:funder] = self.funder_name.present? ? self.funder_name : (self.template.org.present? ? self.template.org.name : '') + + # set the template name and customizer name if applicable + hash[:template] = self.template.title + customizer = "" + cust_questions = self.questions.where(modifiable: true).pluck(:id) + # if the template is customized, and has custom answered questions + if self.template.customization_of.present? && Answer.where(plan_id: self.id, question_id: cust_questions).present? + customizer = _(" Customised By: ") + self.template.org.name + end + hash[:customizer] = customizer + hash + end + + def record_plan_export(format) + exported_plan = ExportedPlan.new.tap do |ep| + ep.plan = self + ep.phase_id = self.phases.first.id + ep.format = format + plan_settings = self.settings(:export) + + Settings::Template::DEFAULT_SETTINGS.each do |key, value| + ep.settings(:export).send("#{key}=", plan_settings.send(key)) + end + end + exported_plan.save + end + end +end \ No newline at end of file diff --git a/app/models/plan.rb b/app/models/plan.rb index 9aa7c51..8c8265b 100644 --- a/app/models/plan.rb +++ b/app/models/plan.rb @@ -1,5 +1,6 @@ class Plan < ActiveRecord::Base include ConditionalUserMailer + include ExportablePlan before_validation :set_creation_defaults ## diff --git a/app/views/plans/export.docx.erb b/app/views/plans/export.docx.erb deleted file mode 100644 index e75c5a4..0000000 --- a/app/views/plans/export.docx.erb +++ /dev/null @@ -1,47 +0,0 @@ -
- <%= admin_field_t(field.to_s) %>: - <%= value.present? ? value : _('-') %> -
- <% end %> -<% end %> - - - -<% @sections.each do |section| %> - <% if @question_headings %> -<%= _('Question not answered') %>
- <% else %> - <% q_format = question.question_format %> - <% if q_format.option_based? %> -| <%= _('Title')%> | -<%= _('Description')%> | -
|---|---|
- <%= admin_field_t(field.to_s) -%> |
- <%= value.present? ? value : _('-') %> | -
| <%= _('Questions')%> | -<%= _('Answers')%> | - <% else %> -- <% end %> - |
|---|---|---|
|
- - <%= raw question.text %> - |
- <% end %>
-
- <% if answer.nil? %>
- <%= _('Question not answered') %> - <% else %> - <% q_format = question.question_format %> - <% if q_format.option_based? %> -
|
-
<%= _("A Data Management Plan created using ") + Rails.configuration.branding[:application][:name] %>
-<%= _("Creator(s): ") + @creator_text %>
<%= _("Affiliation: ") + @affiliation %>
<%= _("Template: ") + @funder %>
<%= _("Template: ") + @template + @customizer %>
<%= _("Grant number: ") + @plan.grant_number %>
<%= _("Project abstract: ") %>
-<%= _("Last modified: ") + @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") %>
<%= _('Question not answered.') -%>
- <% else %> - <% q_format = question.question_format %> - <% if q_format.option_based? %> -<%= _("A Data Management Plan created using ") + Rails.configuration.branding[:application][:name] %>
-<%= _("Creator(s): ") + @creator_text %>
<%= _("Affiliation: ") + @affiliation %>
<%= _("Template: ") + @funder %>
<%= _("Template: ") + @template + @customizer %>
<%= _("Grant number: ") + @plan.grant_number %>
<%= _("Project abstract: ") %>
-<%= _("Last modified: ") + @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") %>
<%= _('Question not answered.') -%>
- <% else %> - <% q_format = question.question_format %> - <% if q_format.option_based? %> -<%= raw question[:text][0].gsub(/
<%= _('Question not answered.') -%>
+ <% else %> + <% if answer.question_options.length > 0 %> +<%= raw answer.text %>
+ <% end %> + <% end %> + + <% end %> + <% end %> + <% end %> + + \ No newline at end of file diff --git a/app/views/shared/export/_plan_coversheet.erb b/app/views/shared/export/_plan_coversheet.erb new file mode 100644 index 0000000..2111156 --- /dev/null +++ b/app/views/shared/export/_plan_coversheet.erb @@ -0,0 +1,34 @@ ++ <%= _("A Data Management Plan created using ") + Rails.configuration.branding[:application][:name] %> +
+<%= @hash[:attribution].length > 1 ? _("Creators: ") : _('Creator:') %> <%= @hash[:attribution].join(', ') %>
<%= _("Affiliation: ") + @hash[:affiliation] %>
<%= _("Template: ") + @hash[:funder] %>
<%= _("Template: ") + @hash[:template] + @hash[:customizer] %>
<%= _("Grant number: ") + @plan.grant_number %>
<%= _("Project abstract: ") %>
+<%= _("Last modified: ") + l(@plan.updated_at.to_date, formats: :short) %>
<%= _("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") %>