diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 1b13b64..008e253 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -68,25 +68,6 @@ redirect_to root_path unless user_signed_in? && (current_user.can_add_orgs? || current_user.can_change_org? || current_user.can_super_admin?) end - def get_plan_list_columns - if user_signed_in? - @selected_columns = current_user.settings(:plan_list).columns - - # handle settings saved and stored using an older version of the settings gem - if @selected_columns.kind_of? Hash - unless @selected_columns['elements'].nil? - @selected_columns = @selected_columns['elements'].collect{|k,v| puts "#{k} - #{v}"; k} - end - end - - # If the settings are missing or stored in the wrong format for some reason - # then use the defaults columns - @selected_columns = Settings::PlanList::DEFAULT_COLUMNS if @selected_columns.empty? - - @all_columns = Settings::PlanList::ALL_COLUMNS - end - end - def failed_create_error(obj, obj_name) "#{_('Could not create your %{o}.') % {o: obj_name}} #{errors_to_s(obj)}" end @@ -113,7 +94,15 @@ def errors_to_s(obj) if obj.errors.count > 0 - "
#{obj.errors.collect{|e,m| "#{_(e)} - #{_(m)}"}.join("
")}" + msg = "
" + obj.errors.each do |e,m| + if m.include?('empty') || m.include?('blank') + msg += "#{_(e)} - #{_(m)}
" + else + msg += "'#{obj[e]}' - #{_(m)}
" + end + end + msg end end end diff --git a/app/controllers/confirmations_controller.rb b/app/controllers/confirmations_controller.rb deleted file mode 100644 index 8070b25..0000000 --- a/app/controllers/confirmations_controller.rb +++ /dev/null @@ -1,9 +0,0 @@ -class ConfirmationsController < Devise::ConfirmationsController - - protected - - def after_confirmation_path_for(resource_name, resource) - root_path - end - -end \ No newline at end of file diff --git a/app/controllers/phases_controller.rb b/app/controllers/phases_controller.rb index de50db4..858b66a 100644 --- a/app/controllers/phases_controller.rb +++ b/app/controllers/phases_controller.rb @@ -162,6 +162,9 @@ @phase.description = params["phase-desc"] @phase.modifiable = true if @phase.save + @phase.template.dirty = true + @phase.template.save! + redirect_to admin_show_phase_path(id: @phase.id, edit: 'true'), notice: _('Information was successfully created.') else flash[:notice] = failed_create_error(@phase, _('phase')) @@ -177,6 +180,9 @@ authorize @phase @phase.description = params["phase-desc"] if @phase.update_attributes(params[:phase]) + @phase.template.dirty = true + @phase.template.save! + redirect_to admin_show_phase_path(@phase), notice: _('Information was successfully updated.') else @sections = @phase.sections @@ -198,6 +204,9 @@ authorize @phase @template = @phase.template if @phase.destroy + @template.dirty = true + @template.save! + redirect_to admin_template_template_path(@template), notice: _('Information was successfully deleted.') else @sections = @phase.sections diff --git a/app/controllers/plans_controller.rb b/app/controllers/plans_controller.rb index e0f6648..140b90f 100644 --- a/app/controllers/plans_controller.rb +++ b/app/controllers/plans_controller.rb @@ -4,7 +4,6 @@ #Uncomment the line below in order to add authentication to this page - users without permission will not be able to add new plans #load_and_authorize_resource # - before_filter :get_plan_list_columns, only: %i( index ) after_action :verify_authorized @@ -38,8 +37,7 @@ def create @plan = Plan.new authorize @plan - @plan.save - + message = "" # if we have a template_id we've been selcting between templates, otherwise funders @@ -56,8 +54,12 @@ funder_templates = get_most_recent( funder.templates.where(published: true).all ) # get org templates and index by customization id - orgtemplates = get_most_recent( current_user.org.templates.all ) - + if current_user.org.nil? + orgtemplates = [] + else + orgtemplates = get_most_recent( current_user.org.templates.all ) + end + orgt_by_customization = orgtemplates.collect{|t| [t.customization_of, t]}.to_h # go through funder templates and replace with org cusomizations if needed @@ -69,6 +71,7 @@ @templates << ft end end + else # either didn't select funder or selected "No Funder" # get all org @templates which are not customisations @@ -105,13 +108,12 @@ @plan.title = _('My plan')+' ('+@plan.template.title+')' # We should use interpolated string since the order of the words from this message could vary among languages - @plan.assign_creator(current_user.id) - @all_guidance_groups = @plan.get_guidance_group_options @selected_guidance_groups = @plan.guidance_groups.pluck(:id) respond_to do |format| if @plan.save + @plan.assign_creator(current_user.id) flash.notice = _('Plan was successfully created.') + message format.html { redirect_to({:action => "show", :id => @plan.id, :editing => true }) } else diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index aaa02e1..ea11160 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -2,9 +2,6 @@ # TODO: Delete this controller! It is no longer in use and `rake routes` does not even map to this any longer - - - before_filter :get_plan_list_columns, only: %i( index ) after_action :verify_authorized # GET /projects diff --git a/app/controllers/questions_controller.rb b/app/controllers/questions_controller.rb index 47f9a11..6ed74f3 100644 --- a/app/controllers/questions_controller.rb +++ b/app/controllers/questions_controller.rb @@ -9,6 +9,9 @@ @question.guidance = params["new-question-guidance"] @question.default_value = params["new-question-default-value"] if @question.save + @question.section.phase.template.dirty = true + @question.section.phase.template.save! + redirect_to admin_show_phase_path(id: @question.section.phase_id, section_id: @question.section_id, question_id: @question.id, edit: 'true'), notice: _('Information was successfully created.') else @edit = (@question.section.phase.template.org == current_user.org) @@ -33,6 +36,9 @@ @section = @question.section @phase = @section.phase if @question.update_attributes(params[:question]) + @question.section.phase.template.dirty = true + @question.section.phase.template.save! + redirect_to admin_show_phase_path(id: @phase.id, section_id: @section.id, question_id: @question.id, edit: 'true'), notice: _('Information was successfully updated.') else @edit = (@phase.template.org == current_user.org) @@ -53,6 +59,9 @@ @section = @question.section @phase = @section.phase if @question.destroy + @phase.template.dirty = true + @phase.template.save! + redirect_to admin_show_phase_path(id: @phase.id, section_id: @section.id, edit: 'true'), notice: _('Information was successfully deleted.') else redirect_to admin_show_phase_path(id: @phase.id, section_id: @section.id, edit: 'true'), notice: failed_destroy_error(@question, 'question') diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb index 8f12488..1cd51ea 100644 --- a/app/controllers/registrations_controller.rb +++ b/app/controllers/registrations_controller.rb @@ -52,6 +52,7 @@ if resource.active_for_authentication? set_flash_message :notice, :signed_up if is_navigational_format? sign_up(resource_name, resource) + UserMailer.welcome_notification(current_user).deliver respond_with resource, location: after_sign_up_path_for(resource) else set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_navigational_format? diff --git a/app/controllers/sections_controller.rb b/app/controllers/sections_controller.rb index e05418c..9880863 100644 --- a/app/controllers/sections_controller.rb +++ b/app/controllers/sections_controller.rb @@ -10,6 +10,9 @@ @section.modifiable = true @phase = @section.phase if @section.save + @section.phase.template.dirty = true + @section.phase.template.save! + redirect_to admin_show_phase_path(id: @section.phase_id, :section_id => @section.id, edit: 'true'), notice: _('Information was successfully created.') else @@ -31,6 +34,9 @@ @section.description = params["section-desc-#{params[:id]}"] @phase = @section.phase if @section.update_attributes(params[:section]) + @section.phase.template.dirty = true + @section.phase.template.save! + redirect_to admin_show_phase_path(id: @phase.id, section_id: @section.id , edit: 'true'), notice: _('Information was successfully updated.') else @edit = (@phase.template.org == current_user.org) @@ -49,7 +55,11 @@ @section = Section.includes(phase: :template).find(params[:section_id]) authorize @section @phase = @section.phase + if @section.destroy + @phase.template.dirty = true + @phase.template.save! + redirect_to admin_show_phase_path(id: @phase.id, edit: 'true' ), notice: _('Information was successfully deleted.') else @edit = (@phase.template.org == current_user.org) diff --git a/app/controllers/settings/plans_controller.rb b/app/controllers/settings/plans_controller.rb index c9be594..c406401 100644 --- a/app/controllers/settings/plans_controller.rb +++ b/app/controllers/settings/plans_controller.rb @@ -1,7 +1,6 @@ module Settings class PlansController < SettingsController - before_filter :get_plan_list_columns before_filter :get_settings after_action :verify_authorized diff --git a/app/controllers/settings/projects_controller.rb b/app/controllers/settings/projects_controller.rb deleted file mode 100644 index 8b0f800..0000000 --- a/app/controllers/settings/projects_controller.rb +++ /dev/null @@ -1,46 +0,0 @@ -module Settings - class ProjectsController < SettingsController - - before_filter :get_plan_list_columns - before_filter :get_settings - - after_action :verify_authorized - - def show - authorize [:settings, Project] - respond_to do |format| - format.html - - format.json{ render json: settings_json } - end - end - - def update - authorize [:settings, Project] - columns = (params[:columns] || {}) - - if @settings.update_attributes(columns: columns) - respond_to do |format| - format.html { redirect_to(projects_path) } - - format.json{ render json: settings_json } - end - else - render(action: :show) # Expect #show to display errors etc - end - end - - private - - def get_settings - @settings = current_user.settings(:plan_list) - # :name column should always be present (displayed as a disabled checkbox) - # so it's not necessary to include it in the list here - @all_columns -= ['name'] - end - - def settings_json - @settings_json ||= { selected_columns: @settings.columns, all_columns: @all_columns }.to_json - end - end -end diff --git a/app/controllers/suggested_answers_controller.rb b/app/controllers/suggested_answers_controller.rb index cfe3da0..e15d0c0 100644 --- a/app/controllers/suggested_answers_controller.rb +++ b/app/controllers/suggested_answers_controller.rb @@ -7,6 +7,10 @@ @suggested_answer = SuggestedAnswer.new(params[:suggested_answer]) authorize @suggested_answer if @suggested_answer.save + # Set the template's dirty flag to true + @suggested_answer.question.section.phase.template.dirty = true + @suggested_answer.question.section.phase.template.save + redirect_to admin_show_phase_path(id: @suggested_answer.question.section.phase_id, section_id: @suggested_answer.question.section_id, question_id: @suggested_answer.question.id, edit: 'true'), notice: _('Information was successfully created.') else @phase = @suggested_answer.question.section.phase @@ -29,6 +33,10 @@ @section = @question.section @phase = @section.phase if @suggested_answer.update_attributes(params[:suggested_answer]) + # Set the template's dirty flag to true + @phase.template.dirty = true + @phase.template.save + redirect_to admin_show_phase_path(id: @phase.id, section_id: @section.id, question_id: @question.id, edit: 'true'), notice: _('Information was successfully updated.') else flash[:notice] = failed_update_error(@suggested_answer, _('suggested answer')) @@ -44,6 +52,10 @@ @section = @question.section @phase = @section.phase if @suggested_answer.destroy + # Set the template's dirty flag to true + @phase.template.dirty = true + @phase.template.save + redirect_to admin_show_phase_path(id: @phase.id, section_id: @section.id, edit: 'true'), notice: _('Information was successfully deleted.') else redirect_to admin_show_phase_path(id: @phase.id, section_id: @section.id, edit: 'true'), notice: flash[:notice] = failed_destroy_error(@suggested_answer, _('suggested answer')) diff --git a/app/controllers/templates_controller.rb b/app/controllers/templates_controller.rb index 965aaeb..b0eeb11 100644 --- a/app/controllers/templates_controller.rb +++ b/app/controllers/templates_controller.rb @@ -6,208 +6,204 @@ respond_to :html after_action :verify_authorized - # GET /dmptemplates + # GET /org/admin/templates/:id/admin_index + # ----------------------------------------------------- def admin_index authorize Template - # institutional templates - all_versions_own_templates = Template.where(org_id: current_user.org_id, customization_of: nil).order(version: :desc) - current_templates = {} - # take most recent version of each template - all_versions_own_templates.each do |temp| - if current_templates[temp.dmptemplate_id].nil? - current_templates[temp.dmptemplate_id] = temp - end - end - @templates_own = current_templates.values - @other_published_version = {} - current_templates.keys.each do |dmptemplate_id| - @other_published_version[dmptemplate_id] = Template.where(org_id: current_user.org_id, dmptemplate_id: dmptemplate_id, published: true).present? - end - - # funders templates - funders_templates = {} - Org.includes(:templates).funder.each do |org| - org.templates.where(customization_of: nil, published: true).order(version: :desc).each do |temp| - if funders_templates[temp.dmptemplate_id].nil? - funders_templates[temp.dmptemplate_id] = temp + + # Collect all of the published funder templates + @funder_templates = [] + Org.funders.each do |org| + Template.dmptemplate_ids.each do |id| + template = Template.live(id) + # Its possible for the template to NOT have a published version + # so only add it if its not nil + unless template.nil? + @funder_templates << {current: template, live: template} end end end - - @templates_funders = funders_templates.values - # are any funder templates customized - @templates_customizations = {} - Template.where(org_id: current_user.org_id, customization_of: funders_templates.keys).order(version: :desc).each do |temp| - if @templates_customizations[temp.customization_of].nil? - @templates_customizations[temp.customization_of] = {} - @templates_customizations[temp.customization_of][:temp] = temp - @templates_customizations[temp.customization_of][:published] = temp.published - else - @templates_customizations[temp.customization_of][:published] = @templates_customizations[temp.customization_of][:published] || temp.published + + # Collect all of the organisations templates + @org_templates = [] + Template.dmptemplate_ids.each do |id| + template = Template.current(id) + live = Template.live(id) + + # Its possible for the template to NOT have a published version + # so only add it if its not nil + unless template.nil? + if template.customization_of.nil? + @org_templates << {current: template, live: live} + + # Check to see if this is a customization of a funder template + # If so replace the funder's copy + else + @funder_templates.delete_if{|t| + t[:current].dmptemplate_id == template.customization_of + } + @funder_templates << {current: template, live: live} + end end 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 + } + end + + # PUT /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.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 + + # 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), notice: _('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 + + # Create a new version + new_version = Template.deep_copy(@template) + new_version.version = (@template.version + 1) + new_version.published = false + new_version.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 - # GET /dmptemplates/1 + # Unpublish the live version + @template = Template.live(template.dmptemplate_id) + + if @template.nil? + flash[:notice] = _('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, :suggested_answers]]]).find(params[:id]) - # check to see if this is a funder template needing customized - authorize @template - if @template.org_id != current_user.org_id - # definitely need to deep_copy the given 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 - # need to mark all Phases, questions, sections as not-modifiable - 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: :suggested_answers ]]).where(org_id: current_user.org_id, customization_of: @template.dmptemplate_id).order(version: :desc) - if customizations.present? - # existing customization 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 customized 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: :suggested_answers]).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 suggested_answers - question.suggested_answers.each do |suggested_answer| - suggested_answer_copy = SuggestedAnswer.deep_copy(suggested_answer) - suggested_answer_copy.org_id = current_user.org_id - suggested_answer_copy.question_id = customization_question.id - suggested_answer_copy.save! - end - # guidance attached to a question is also a form of customization - # It will soon become an annotation of the question, and be combined with - # suggested answers - customization_question.guidance = customization_question.guidance + question.guidance - customization_question.save! - end - end - end - end - end - else - # first time customization - new_customization.version = 0 - new_customization.dmptemplate_id = loop do - random = rand 2147483647 # max int field in psql - break random unless Template.exists?(dmptemplate_id: random) - end - end - new_customization.save! - @template = new_customization + + @current = Template.current(@template.dmptemplate_id) + + unless @template == @current + flash[:notice] = _('You are viewing a historical version of this template. You will not be able to make changes.') end - # needed for some post-migration edge cases - # some customized templates which were edited - if @template.published - 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 @hash = @template.to_hash end - # PUT /dmptemplates/1 + # PUT /org/admin/templates/:id/admin_update + # ----------------------------------------------------- def admin_update @template = Template.find(params[:id]) authorize @template - if @template.published? - # published templates cannot be edited - redirect_to admin_template_template_path(@template), notice: _('Published templates cannot be edited.') and return - end - @template.description = params["template-desc"] - if @template.update_attributes(params[:template]) - if @template.published? - # unpublish older versions - Template.where("dmptemplate_id = ? AND published = ? AND version < ?", - @template.dmptemplate_id, true, @template.version).each do |t| - t.published = false - t.save - end - - # create a new template version if this template became published - new_version = Template.deep_copy(@template) - new_version.version = @template.version + 1 - new_version.published = false - new_version.save! - end - redirect_to admin_template_template_path(), notice: _('Information was successfully updated.') + + 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"] + if @template.update_attributes(params[:template]) + flash[:notice] = _('Information was successfully updated.') + + else + flash[:notice] = failed_update_error(@template, _('template')) + end + @hash = @template.to_hash - flash[:notice] = failed_update_error(@template, _('template')) render 'admin_template' - end + end end - # GET /dmptemplates/new + # GET /org/admin/templates/:id/admin_new + # ----------------------------------------------------- def admin_new authorize Template end - # POST /dmptemplates - # creates a new template with version 0 and new dmptemplate_id + # 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'] - @template.published = false - @template.version = 0 - @template.visibility = 0 - - # Generate a unique identifier for the dmptemplate_id - @template.dmptemplate_id = loop do - random = rand 2147483647 - break random unless Template.exists?(dmptemplate_id: random) - end if @template.save redirect_to admin_template_template_path(@template), notice: _('Information was successfully created.') @@ -219,24 +215,36 @@ end - # DELETE /dmptemplates/1 + # DELETE /org/admin/templates/:id/admin_destroy + # ----------------------------------------------------- def admin_destroy @template = Template.find(params[:id]) authorize @template - if @template.destroy - redirect_to admin_index_template_path + + 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 - @hash = @template.to_hash - flash[:notice] = failed_destroy_error(@template, _('template')) - render admin_template_template_path(@template) + flash[:notice] = _('You cannot delete historical versions of this template.') + redirect_to admin_index_template_path end end - # GET /templates/1 + # 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 end \ No newline at end of file diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index 90c6278..44efc03 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -1,12 +1,20 @@ class UserMailer < ActionMailer::Base default from: Rails.configuration.branding[:organisation][:email] + def welcome_notification(user) + @user = user + FastGettext.with_locale FastGettext.default_locale do + mail(to: @user.email, + subject: "#{_('Welcome to')} #{Rails.configuration.branding[:application][:name]}") + end + end + def sharing_notification(role, user) @role = role @user = user FastGettext.with_locale FastGettext.default_locale do mail(to: @role.user.email, - subject: _("You have been given access to a Data Management Plan")) + subject: "#{_('A Data Management Plan in ')} #{Rails.configuration.branding[:application][:name]} #{_(' has been shared with you')}") end end @@ -14,7 +22,7 @@ @role = role FastGettext.with_locale FastGettext.default_locale do mail(to: @role.user.email, - subject: _("DMP permissions changed")) + subject: "#{_('Changed permissions on a DMP in')} #{Rails.configuration.branding[:application][:name]}") end end @@ -23,7 +31,7 @@ @plan = plan FastGettext.with_locale FastGettext.default_locale do mail(to: @user.email, - subject: _("DMP access removed")) + subject: "#{_('Permissions removed on a DMP in')} #{Rails.configuration.branding[:application][:name]}") end end @@ -31,7 +39,7 @@ @user = user FastGettext.with_locale FastGettext.default_locale do mail(to: @user.email, - subject: _('API Permission Granted')) + subject: "#{_('API rights in')} #{Rails.configuration.branding[:application][:name]}") end end end \ No newline at end of file diff --git a/app/models/phase.rb b/app/models/phase.rb index d3e813a..1417661 100644 --- a/app/models/phase.rb +++ b/app/models/phase.rb @@ -5,7 +5,6 @@ # [+Copyright:+] Digital Curation Centre and University of California Curation Center class Phase < ActiveRecord::Base # extend FriendlyId - ## # Associations belongs_to :template @@ -25,11 +24,7 @@ validates :title, :number, :template, presence: {message: _("can't be blank")} - - - - - + # EVALUATE CLASS AND INSTANCE METHODS BELOW # # What do they do? do they do it efficiently, and do we need them? @@ -104,4 +99,5 @@ end return phase_copy end + end diff --git a/app/models/question.rb b/app/models/question.rb index eac588d..336cae9 100644 --- a/app/models/question.rb +++ b/app/models/question.rb @@ -1,5 +1,4 @@ class Question < ActiveRecord::Base - ## # Associations has_many :answers, :dependent => :destroy @@ -29,7 +28,6 @@ validates :text, :section, :number, presence: {message: _("can't be blank")} - # EVALUATE CLASS AND INSTANCE METHODS BELOW # # What do they do? do they do it efficiently, and do we need them? diff --git a/app/models/section.rb b/app/models/section.rb index 2a38972..abf1327 100644 --- a/app/models/section.rb +++ b/app/models/section.rb @@ -1,5 +1,4 @@ class Section < ActiveRecord::Base - ## # Associations belongs_to :phase @@ -47,5 +46,4 @@ end return section_copy end - end diff --git a/app/models/settings/plan_list.rb b/app/models/settings/plan_list.rb deleted file mode 100644 index 01d5c88..0000000 --- a/app/models/settings/plan_list.rb +++ /dev/null @@ -1,21 +0,0 @@ -module Settings - class PlanList < RailsSettings::SettingObject - - #attr_accessible :var, :target, :target_type, :target_id - - # TODO: can these be taken from somewhere else rather than hard-coded here? - DEFAULT_COLUMNS = ['name', 'owner', 'shared', 'last_edited'] - ALL_COLUMNS = DEFAULT_COLUMNS + ['template_owner', 'identifier', 'grant_number', 'visibility', - 'principal_investigator', 'data_contact', 'description'] - - validate do - cols = value["columns"] - - if cols.present? # columns can be empty, in which case they revert to defaults - errors.add(:columns, _("'name' must be included in column list.")) unless cols.member?("name") - errors.add(:columns, _('Duplicate column name. Please only include each column once.')) unless cols.keys.uniq == cols.keys - errors.add(:columns, _('Unknown column name.')) unless (cols.keys.uniq & ALL_COLUMNS) == cols.keys.uniq - end - end - end -end diff --git a/app/models/template.rb b/app/models/template.rb index 598f832..63b4b3e 100644 --- a/app/models/template.rb +++ b/app/models/template.rb @@ -1,6 +1,8 @@ class Template < ActiveRecord::Base include GlobalHelpers - + + before_validation :set_creation_defaults + ## # Associations belongs_to :org @@ -26,18 +28,20 @@ validates :org, :title, :version, presence: {message: _("can't be blank")} - # Helper scopes to get the latest version and the latest published version - scope :current, ->(dmptemplate_id) { where(dmptemplate_id: dmptemplate_id).order(version: :desc).first } - scope :published, ->(dmptemplate_id) { where(dmptemplate_id: dmptemplate_id, published: true).order(version: :desc).first } + # Retrieves the list of all dmptemplate_ids (template versioning families) for the specified Org + def self.dmptemplate_ids + Template.all.distinct.pluck(:dmptemplate_id) + end - # Helper scope to get the dmptemplate_ids for the specified org - scope :family_ids, ->(org_id) { where(org_id: org_id).pluck(:dmptemplate_id).distinct } - - - # EVALUATE CLASS AND INSTANCE METHODS BELOW - # - # What do they do? do they do it efficiently, and do we need them? - + # Retrieves the most recent version of the template for the specified Org and dmptemplate_id + def self.current(dmptemplate_id) + Template.where(dmptemplate_id: dmptemplate_id).order(version: :desc).first + end + + # Retrieves the current published version of the template for the specified Org and dmptemplate_id + def self.live(dmptemplate_id) + Template.where(dmptemplate_id: dmptemplate_id, published: true).first + end ## # deep copy the given template and all of it's associations @@ -55,6 +59,12 @@ return template_copy end + + # EVALUATE CLASS AND INSTANCE METHODS BELOW + # + # What do they do? do they do it efficiently, and do we need them? + + ## # convert the given template to a hash and return with all it's associations # to use, please pre-fetch org, phases, section, questions, suggested_answers, @@ -111,4 +121,25 @@ return !modifiable end + # -------------------------------------------------------- + private + # Initialize the published and dirty flags for new templates + def set_creation_defaults + # Only run this before_validation because rails fires this before save/create + if self.id.nil? + self.published = false + self.dirty = false + self.visibility = 1 + self.version = 0 if self.version.nil? + + # Generate a unique identifier for the dmptemplate_id if necessary + if self.dmptemplate_id.nil? + self.dmptemplate_id = loop do + random = rand 2147483647 + break random unless Template.exists?(dmptemplate_id: random) + end + end + end + end + end diff --git a/app/models/user.rb b/app/models/user.rb index 4cfa675..352b564 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -7,7 +7,7 @@ # :token_authenticatable, :confirmable, # :lockable, :timeoutable and :omniauthable devise :invitable, :database_authenticatable, :registerable, :recoverable, - :rememberable, :trackable, :validatable, :confirmable, :omniauthable, + :rememberable, :trackable, :validatable, :omniauthable, :omniauth_providers => [:shibboleth, :orcid] ## @@ -52,14 +52,6 @@ validates :email, email: true, allow_nil: true, uniqueness: {message: _("must be unique")} ## - # Settings - # FIXME: The duplication in the block is to set defaults. It might be better if - # they could be set in Settings::PlanList itself, if possible. - has_settings :plan_list, class_name: 'Settings::PlanList' do |s| - s.key :plan_list, defaults: { columns: Settings::PlanList::DEFAULT_COLUMNS } - end - - ## # Scopes default_scope { includes(:org, :perms, :plans) } diff --git a/app/policies/template_policy.rb b/app/policies/template_policy.rb index 3c9fb80..eeda053 100644 --- a/app/policies/template_policy.rb +++ b/app/policies/template_policy.rb @@ -20,6 +20,18 @@ 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) diff --git a/app/views/devise/mailer/reset_password_instructions.html.erb b/app/views/devise/mailer/reset_password_instructions.html.erb index 21ba9ff..55858c9 100644 --- a/app/views/devise/mailer/reset_password_instructions.html.erb +++ b/app/views/devise/mailer/reset_password_instructions.html.erb @@ -1,10 +1,13 @@ <% FastGettext.with_locale FastGettext.default_locale do %> -

<%= _("Hello") %> <%= @resource.email %>!

+

<%= _("Hello ") %><%= @resource.email %>

-

<%= _("Someone has requested a link to change your") %> <%= link_to Rails.configuration.branding[:application][:name], root_url %> <%= _("password. You can do this through the link below.") %>

+

<%= _("Someone has requested a link to change your ") %><%= Rails.configuration.branding[:application][:name] %><%= _(" password. You can do this through the link below.") %>

-

<%= link_to _('Change my password'), edit_password_url(@resource, :reset_password_token => @token) %>

+

<%= link_to _('Change my password'), edit_password_url(@resource, :reset_password_token => @token) %>

-

<%= _("If you didn't request this, please ignore this email.") %>

-

<%= _("Your password won't change until you access the link above and create a new one.") %>

+

<%= _("If you didn't request this, please ignore this email.") %>

+ +

+ <%= _("Many thanks,") %>
<%= _('The ') %><%= Rails.configuration.branding[:application][:name] %><%= _(' team') %> +

<% end %> \ No newline at end of file diff --git a/app/views/layouts/_navigation.html.erb b/app/views/layouts/_navigation.html.erb index 4ed662d..57bfe0b 100644 --- a/app/views/layouts/_navigation.html.erb +++ b/app/views/layouts/_navigation.html.erb @@ -48,10 +48,6 @@
  • > <%= link_to _('Help'), help_path %>
  • - -
  • > - <%= link_to _('Public DMPs'), public_plans_path %> -
  • <% if MANY_LANGUAGES %>