diff --git a/app/controllers/plans_controller.rb b/app/controllers/plans_controller.rb index 20be939..1d20731 100644 --- a/app/controllers/plans_controller.rb +++ b/app/controllers/plans_controller.rb @@ -7,6 +7,8 @@ def index authorize Plan @plans = current_user.active_plans + # Exclude any plans where the user is a reviewer. They access those plans via Admin -> Plans menu + @plans.delete_if{ |p| p.reviewable_by?(current_user) } @paginable = params[:page] @organisationally_or_publicly_visible = @paginable.nil? ? Plan.organisationally_or_publicly_visible(current_user) : Plan.organisationally_or_publicly_visible(current_user).page(params[:page]) @@ -179,6 +181,8 @@ @plan = Plan.find(params[:id]) if @plan.present? authorize @plan + # Get the roles where the user is not a reviewer + @plan_roles = @plan.roles.select{ |r| !r.reviewer? } else redirect_to(plans_path) end @@ -338,6 +342,25 @@ end end + def request_feedback + @plan = Plan.find(params[:id]) + authorize @plan + alert = _('Unable to submit your request for feedback at this time.') + + begin + if @plan.request_feedback(current_user) + flash[:notice] = _('Your request for feedback has been submitted.') + else + flash[:alert] = alert + end + rescue Exception + flash[:alert] = alert + end + # Get the roles where the user is not a reviewer + @plan_roles = @plan.roles.select{ |r| !r.reviewer? } + render 'share' + end + private def plan_params params.require(:plan).permit(:org_id, :org_name, :funder_id, :funder_name, :template_id, :title, :visibility, diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index afa3b5e..79646ae 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -1,6 +1,6 @@ class UserMailer < ActionMailer::Base default from: Rails.configuration.branding[:organisation][:email] - + def welcome_notification(user) @user = user FastGettext.with_locale FastGettext.default_locale do @@ -31,10 +31,10 @@ def project_access_removed_notification(user, plan, current_user) @user = user @plan = plan - @current_user = current_user + @current_user = current_user FastGettext.with_locale FastGettext.default_locale do mail(to: @user.email, - subject: "#{_('Permissions removed on a DMP in')} #{Rails.configuration.branding[:application][:name]}") + subject: "#{_('Permissions removed on a DMP in %{tool_name}') %{ :tool_name => Rails.configuration.branding[:application][:name] }}") end end @@ -46,25 +46,34 @@ end end - def feedback_notification(user, plan) - @user = user - - if user.org.present? - @org = org + def feedback_notification(recipient, plan, requestor) + @user = requestor + + if @user.org.present? + @org = @user.org @plan = plan + @recipient = recipient - # Use the generic feedback message unless the Org has specified one - subject = org.feedback_email_subject ||= EMAIL_FEEDBACK_REQUESTED_CONFIRMATION_SUBJECT + FastGettext.with_locale FastGettext.default_locale do + mail(to: recipient.email, + subject: _("%{application_name}: %{user_name} requested feedback on a plan") % {application_name: Rails.configuration.branding[:application][:name], user_name: @user.name(false)}) + end + end + end + + def feedback_confirmation(recipient, plan, requestor) + @user = requestor + + if @user.org.present? + @org = @user.org + @plan = plan + + # Use the generic feedback confirmation message unless the Org has specified one + subject = feedback_constant_to_text(@org.feedback_email_subject.present? ? @org.feedback_email_subject : feedback_confirmation_default_subject) + message = feedback_constant_to_text(@org.feedback_email_msg.present? ? @org.feedback_email_msg : feedback_confirmation_default_message) - # Send an email to all of the org admins as well as the Org's administrator email - emails = user.org.users.select{ |usr| usr.can_org_admin? && usr != user } - emails << user.org.contact_email if user.org.contact_email.present? - - emails.each do |email| - @email = email - FastGettext.with_locale FastGettext.default_locale do - mail(to: email, subject: subject) - end + FastGettext.with_locale FastGettext.default_locale do + mail(to: recipient.email, subject: subject, body: message) end end end @@ -77,6 +86,7 @@ subject: _('DMP Visibility Changed: %{plan_title}') %{ :plan_title => @plan.title }) end end + # @param commenter - User who wrote the comment # @param plan - Plan for which the comment is associated to def new_comment(commenter, plan) @@ -91,4 +101,22 @@ end end end + + def feedback_confirmation_default_subject + _('%{application_name}: Your plan has been submitted for feedback') + end + + def feedback_confirmation_default_message + _('
Hello %{user_name}.
'\ + 'Your plan "%{plan_name}" has been submitted for feedback from an administrator at your organisation. '\ + 'If you have questions pertaining to this action, please contact us at %{organisation_email}.
') + end + + private + def feedback_constant_to_text(text) + return _("#{text}") % {application_name: Rails.configuration.branding[:application][:name], + user_name: @user.name, + plan_name: @plan.title, + organisation_email: @org.contact_email} + end end diff --git a/app/models/org.rb b/app/models/org.rb index dde3833..9a93736 100644 --- a/app/models/org.rb +++ b/app/models/org.rb @@ -142,6 +142,11 @@ end end + def org_admins + User.joins(:perms).where("users.org_id = ? AND perms.name IN (?)", self.id, + ['grant_permissions', 'modify_templates', 'modify_guidance', 'change_org_details']) + end + private ## # checks size of logo and resizes if necessary diff --git a/app/models/plan.rb b/app/models/plan.rb index 91e17a5..96086dd 100644 --- a/app/models/plan.rb +++ b/app/models/plan.rb @@ -38,7 +38,7 @@ :exported_plans, :project, :title, :template, :grant_number, :identifier, :principal_investigator, :principal_investigator_identifier, :description, :data_contact, :funder_name, :visibility, :exported_plans, - :roles, :users, :org, :data_contact_email, :data_contact_phone, + :roles, :users, :org, :data_contact_email, :data_contact_phone, :feedback_requested, :principal_investigator_email, :as => [:default, :admin] accepts_nested_attributes_for :roles @@ -189,8 +189,40 @@ end return ggroups.uniq end + + ## + # Sets up the plan for feedback: + # emails confirmation messages to owners + # emails org admins and org contact + # adds org admins to plan with the 'reviewer' Role + def request_feedback(user) + val = Role.access_values_for(:reviewer, :commenter).min + self.feedback_requested = true + + # Share the plan with each org admin as the reviewer role + admins = user.org.org_admins + admins.each do |admin| + self.roles << Role.new(user: admin, access: val) + end - + if self.save! + # Send an email confirmation to the owners and co-owners + self.owner_and_coowners.each do |owner| + UserMailer.feedback_confirmation(owner, self, user).deliver_now + end + + # Send an email to all of the org admins as well as the Org's administrator email + if user.org.contact_email.present? + admins << User.new(email: user.org.contact_email, firstname: user.org.contact_name) + end + admins.each do |admin| + UserMailer.feedback_notification(admin, self, user).deliver_now + end + true + else + false + end + end ## @@ -320,6 +352,17 @@ end ## + # determines if the plan is reviewable by the specified user + # + # @param user_id [Integer] the id for the user + # @return [Boolean] true if the user can administer the plan + def reviewable_by?(user_id) + user_id = user_id.id if user_id.is_a?(User) + role = roles.where(user_id: user_id).first + return role.present? && role.reviewer? + end + + ## # determines whether or not the specified user has any rol on the plan # # @param user_id [Integer] the id for the user @@ -573,6 +616,15 @@ end ## + # the owner and co-owners of the project + # + # @return [Users] + def owner_and_coowners + vals = Role.access_values_for(:creator).concat(Role.access_values_for(:administrator)) + User.joins(:roles).where("roles.plan_id = ? AND roles.access IN (?)", self.id, vals) + end + + ## # the time the project was last updated, formatted as a date # # @return [Date] last update as a date diff --git a/app/models/role.rb b/app/models/role.rb index 28f63f1..7ccdde4 100644 --- a/app/models/role.rb +++ b/app/models/role.rb @@ -15,6 +15,7 @@ 2 => :administrator, # 2 3 => :editor, # 4 4 => :commenter, # 8 + 5 => :reviewer, # 16 column: 'access' validates :user, :plan, :access, presence: {message: _("can't be blank")} @@ -22,6 +23,7 @@ ## # return the access level for the current project group + # 5 if the user is a reviewer # 3 if the user is an administrator # 2 if the user is an editor # 1 if the user can only read @@ -29,7 +31,9 @@ # # @return [Integer] def access_level - if self.administrator? + if self.reviewer? + return 5 + elsif self.administrator? return 3 elsif self.editor? return 2 @@ -41,6 +45,11 @@ # This method becomes useful for generatic template messages (e.g. permissions change notification mailer) def self.access_level_messages { + 5 => { + :type => _('reviewer'), + :placeholder1 => _('read the plan and provide feedback.'), + :placeholder2 => nil + }, 3 => { :type => _('co-owner'), :placeholder1 => _('write and edit the plan in a collaborative manner.'), @@ -82,4 +91,20 @@ # 12 - editor + commenter # 13 - creator + editor + commenter # 14 - administrator + editor + commenter -# 15 - creator + administrator + editor + commenter \ No newline at end of file +# 15 - creator + administrator + editor + commenter +# 16 - reviewer +# 17 - creator + reviewer +# 18 - administrator + reviewer +# 19 - creator + administrator + reviewer +# 20 - editor + reviewer +# 21 - creator + editor + reviewer +# 22 - administraor + editor + reviewer +# 23 - creator + editor + administrator + reviewer +# 24 - commenter + reviewer +# 25 - creator + commenter + reviewer +# 26 - administrator + commenter + reviewer +# 27 - creator + administrator + commenter + reviewer +# 28 - editor + commenter + reviewer +# 29 - creator + editor + commenter + reviewer +# 30 - administrator + editor + commenter + reviewer +# 31 - creator + administrator + editor + commenter + reviewer \ No newline at end of file diff --git a/app/policies/plan_policy.rb b/app/policies/plan_policy.rb index 8fd7e88..11dd045 100644 --- a/app/policies/plan_policy.rb +++ b/app/policies/plan_policy.rb @@ -53,4 +53,7 @@ @plan.readable_by?(@user.id) && Role.find_by(user_id: @user.id, plan_id: @plan.id).active end + def request_feedback? + @plan.owned_by?(@user.id) && Role.find_by(user_id: @user.id, plan_id: @plan.id).active + end end diff --git a/app/views/orgs/_feedback_form.html.erb b/app/views/orgs/_feedback_form.html.erb index dce7405..2d651fd 100644 --- a/app/views/orgs/_feedback_form.html.erb +++ b/app/views/orgs/_feedback_form.html.erb @@ -11,12 +11,11 @@<%= _('Click below to give data management staff at your organisation access to read and comment on your plan.') %>
+<%= _('You can continue to edit and download the plan in the interim.') %>
+ +<%= _('Hello %{user_name},') % {user_name: recipient_name} %>
+<%= _('%{requestor} has requested feedback on a plan "%{plan_name}." To add comments, please visit the \'Plans\' page under the Admin menu in %{application_name} and open the plan.') % {requestor: requestor_name, plan_name: plan_name, application_name: tool_name} %>
+<%= _('All the best,
The %{application_name} team') % {application_name: tool_name} %>
<%= _('You may change your notification preferences on your profile page. Please do not reply to this email. If you have questions or need help, please contact us at %{help_desk} or visit %{contact_url}') % {help_desk: helpdesk, contact_url: contact_url} %>
+<% end %> \ No newline at end of file diff --git a/config/initializers/constants.rb b/config/initializers/constants.rb index d8952b8..c3f0124 100644 --- a/config/initializers/constants.rb +++ b/config/initializers/constants.rb @@ -1,11 +1,3 @@ LANGUAGES = (ActiveRecord::Base.connection.table_exists? 'languages') ? Language.sorted_by_abbreviation : [] MANY_LANGUAGES = LANGUAGES.length > 1 TABLE_FILTER_MIN_ROWS = 10 - -# Default Feedback Request Email sent to the requesting user -# This email can be overriden by local Org Admins on the Org Details page -# TODO: Move this to a location that gets loaded AFTER FastGettext so that we can use fastgettext to manage localisations -EMAIL_FEEDBACK_REQUESTED_CONFIRMATION_SUBJECT = 'Your DMP has been submitted for feedback in %{application_name}' -EMAIL_FEEDBACK_REQUESTED_CONFIRMATION_MESSAGE = 'Hello [user_name],
'\ - 'Your DMP "[plan_name]" has been submitted for feedback from an administrator at your institution. If you have questions pertaining to this action, please contact your local administrator at [organisation_email].
'\ - 'All the best,
The %{application_name} team.