CSC/ECE 517 Fall 2017/E1758 Improve e-mail notifications
Introduction
Expertiza is a web application developed using Ruby on Rails that serves as a peer-review system. The application allows students to submit and peer-review learning objects (articles, code, web sites, etc)[1][2]. It is an open source project and it's codebase is maintained in GitHub. We are contributing to Expertiza as a part of our Object-Oriented Design and Development's Open-Source Software (OSS) Project. Our goal in this project is to fix various issues related to staggered deadlines for assignments. A staggered-deadline assignment is an assignment in which different topics have different deadlines. In this Wiki Page, we will explain the changes that we have made for the same.
Changes To Be Implemented
- What’s wrong:
- There are also other circumstances when it would be helpful to send mail.
Modified Files
- app/controllers/invitations_controller.rb
- app/controllers/submitted_content_controller.rb
- app/controllers/suggestion_controller.rb
- app/mailers/mailer.rb
- app/models/assignment.rb
- app/models/assignment_participant.rb
- app/models/course_participant.rb
Added Files
- app/views/mailer/partials/_user_invite_html.html.erb
- app/views/mailer/partials/_user_invite_plain.html.erb
- app/views/mailer/partials/_user_welcome_html.html.erb
- app/views/mailer/partials/_user_welcome_plain.html.erb
- app/views/mailer/send_mail_to_instructor.html.erb
- app/views/mailer/send_mail_to_instructor.text.erb
- app/views/mailer/partials/_user_accept_html.html.erb
- app/views/mailer/partials/_user_accept_plain.html.erb
- app/views/mailer/partials/_user_decline_html.html.erb
- app/views/mailer/partials/_user_decline_plain.html.erb
Approach Taken To Implement Changes
NOTE: All the mails except the ones for the reviewer which are sent to mailinator , are sent to expertiza.development@gmail.com ,as this is already set in the development environment.
1) Initially the email were being sent to users when they were added using a CSV file on the users page only . Now we added a method in the assignment_participant.rb model to send mails when a participant is added to an assignment on the assignment page through a CSV file.
def self.import(row, _row_header = nil, session, id)
raise ArgumentError, "No user id has been specified." if row.empty? user = User.find_by_name(row[0]) if user.nil? raise ArgumentError, "The record containing #{row[0]} does not have enough items." if row.length < 4 attributes = ImportFileHelper.define_attributes(row) user = ImportFileHelper.create_new_user(attributes, session) end raise ImportError, "The assignment with id \"" + id.to_s + "\" was not found." if Assignment.find(id).nil? unless AssignmentParticipant.exists?(user_id: user.id, parent_id: id) new_part = AssignmentParticipant.create(user_id: user.id, parent_id: id) new_part.set_handle # E1758 Fall17 password = "password"#user.password prepared_mail = MailerHelper.send_mail_to_user(user, "Your Expertiza account and password have been created.", "user_welcome", password) prepared_mail.deliver end end
Also we added a method in the course_participant.rb file to send the mails when the user is added on the course page using a CSV file.
def self.import(row, _row_header = nil, session, id) raise ArgumentError, "No user id has been specified." if row.empty? user = User.find_by_name(row[0]) if user.nil? raise ArgumentError, "The record containing #{row[0]} does not have enough items." if row.length < 4 attributes = ImportFileHelper.define_attributes(row) user = ImportFileHelper.create_new_user(attributes, session) end course = Course.find(id) if course.nil? raise ImportError, "The course with the id \"" + id.to_s + "\" was not found." end unless CourseParticipant.exists?(user_id: user.id, parent_id: course.id) CourseParticipant.create(user_id: user.id, parent_id: course.id) # E1758 Fall 17 password = "password"#user.password prepared_mail = MailerHelper.send_mail_to_user(user, "Your Expertiza account and password have been created.", "user_welcome", password) prepared_mail.deliver end end
2) Initially whenever a submission was being revised ,a mail was being sent to the the reviewer to revise the review. We needed to make sure that mail should not go when it is the last phase of review.
We put a check on the condition that if it is the last round of review then mail should not be sent to the reviewer for revision of his review. for that we created a method review_deadline in the assignment.rb file to check if the next due date round is equal to number of review rounds or not.
- E1758 Fall 17
def review_deadline(topic_id = nil, num_review_rounds) return false if topic_id.nil? and self.staggered_deadline? next_due_date = DueDate.get_next_due_date(self.id, topic_id) return !(next_due_date.round == num_review_rounds && next_due_date.deadline_type_id == 2) end
We also created a method in the assignment_participant.rb file to check if the round is valid for mail.
# E1758 Fall 17 def is_round_valid_for_mail? topic_id = SignedUpTeam.topic_id(self.parent_id, self.user_id) return assignment.review_deadline(topic_id, assignment.num_review_rounds) end
end
In the submitted_content_controller.rb we created a check
# E1758 Fall 17 if participant.is_round_valid_for_mail? reviewers = [] participant.reviewers.each do |reviewer| reviewers << User.find(reviewer.user_id).email end Mailer.delayed_message(bcc: reviewers, subject: "You have a new submission to be review", body: "Please visit http://expertiza.ncsu.edu and proceed to peer reviews.").deliver_now # participant.assignment.email(participant.id) rescue nil end end redirect_to action: 'edit', id: @participant.id end
3) Initially no mail was going to the reciever when a participant was sending an invitation to another participant. We have edited the create method to put the mail functionality in invitations controller
def create
# check if the invited user is already invited (i.e. awaiting reply) if Invitation.is_invited?(@student.user_id, @user.id, @student.parent_id) create_utility # E1758 Fall 17 MailerHelper.send_mail_to_invitee(@user, "You have been invited to join a team", "user_invite").deliver #password = "password" #prepared_mail = MailerHelper.send_mail_to_user(@user, "You have been invited to join a team", "user_welcome", password) #prepared_mail.deliver else flash[:note] = "You have already sent an invitation to \"#{@user.name}\"." end
update_join_team_request @user, @student
redirect_to view_student_teams_path student_id: @student.id end
we also created two partials for the respective view namely.
- app/views/mailer/partials/_user_invite_html.html.erb
- app/views/mailer/partials/_user_invite_plain.html.erb
4) As there was no mailing method for invitation there was also no method to notify the sender of invitation about the acceptance of his invitation. For this we made changes in the accept and decline methods of the invitations controller.
def accept
# Accept the invite and check whether the add was successful @inv = Invitation.find(params[:inv_id]) sender_student = @inv.from_user # E1758 Fall 17 MailerHelper.send_mail_to_invitee(sender_student, "Invitation accepted.", "user_invite_accept").deliver unless Invitation.accept_invite(params[:team_id], @inv.from_id, @inv.to_id, @student.parent_id) flash[:error] = 'The system failed to add you to the team that invited you.' end
redirect_to view_student_teams_path student_id: params[:student_id] end
def decline @inv = Invitation.find(params[:inv_id]) # Status code D for declined @inv.reply_status = 'D' @inv.save student = Participant.find(params[:student_id]) sender_student = @inv.from_user # E1758 Fall 17 MailerHelper.send_mail_to_invitee(sender_student, "Invitation declined.", "user_invite_decline").deliver redirect_to view_student_teams_path student_id: student.id end
Apart from that we created four partials for the respective changes,namely:
- app/views/mailer/partials/_user_accept_html.html.erb
- app/views/mailer/partials/_user_accept_plain.html.erb
- app/views/mailer/partials/_user_decline_html.html.erb
- app/views/mailer/partials/_user_decline_plain.html.erb
5) When a student suggests a topic initially the instructor was not notified. We created a method send_mail_to_instructor() to send mails in the mailer.rb.
# E1758 Fall 17 def send_mail_to_instructor() #just for development purpose, else parameters can be passed accordingly mail(to:'expertiza.development@gmail.com',subject: "A new topic suggestion by student") end
We called the above defined method in the suggestion_controller.
# E1758 Fall 17 Mailer.send_mail_to_instructor().deliver_now redirect_to action: 'new', id: @suggestion.assignment_id
Now the instructor is recieving mail when a student is suggesting a topic.
We also added two views which consist of the respective mail content.
- app/views/mailer/send_mail_to_instructor.html.erb
- app/views/mailer/send_mail_to_instructor.text.erb
Testing
Our project requirements does not include designing automated test cases so we have done manual testing to make sure that it works well. The manual testing is shown in the video.
Additional Links
- Git pull link: https://github.com/expertiza/expertiza/pull/1048
- Git compare link: https://github.com/expertiza/expertiza/compare/master...pmg007:pmg?expand=1