diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000000..2f1d69f05e1 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,27 @@ +# Use an official Ruby runtime as a parent image +FROM ruby:2.7 + +# Install dependencies +RUN apt-get update -qq && apt-get install -y nodejs postgresql-client + +# Set up the working directory +WORKDIR /app + +# Copy the Gemfile and Gemfile.lock into the container +COPY Gemfile /app/Gemfile +COPY Gemfile.lock /app/Gemfile.lock + +# Install gems +RUN bundle install + +# Copy the rest of the application files into the container +COPY . /app + +# Precompile assets (if your app has assets) +RUN bundle exec rake assets:precompile || true + +# Expose the port that the app runs on +EXPOSE 3000 + +# Start the server by default +CMD ["rails", "server", "-b", "0.0.0.0"] diff --git a/E2460-MentorMeetingManagement b/E2460-MentorMeetingManagement new file mode 160000 index 00000000000..c1e6c750acc --- /dev/null +++ b/E2460-MentorMeetingManagement @@ -0,0 +1 @@ +Subproject commit c1e6c750acc39255283558f7b97c869f644f09a3 diff --git a/README.md b/README.md index 57d9118cade..6488ca3535d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,13 @@ Expertiza ========= +MMM Last Semester's Pull Requests +Pull Request: (https://github.com/expertiza/expertiza/pull/2769) +Pull Request: (https://github.com/expertiza/expertiza/pull/2772) + +Their Wiki (https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Spring_2024_-_E2403_Mentor-Meeting_Management) + + [![Build Status](https://travis-ci.org/expertiza/expertiza.svg?branch=main)](https://travis-ci.org/expertiza/expertiza) [![Coverage Status](https://coveralls.io/repos/github/expertiza/expertiza/badge.svg?branch=main)](https://coveralls.io/github/expertiza/expertiza?branch=main) [![Maintainability](https://api.codeclimate.com/v1/badges/23b8a211854207919986/maintainability)](https://codeclimate.com/github/expertiza/expertiza/maintainability) diff --git a/app/controllers/mentor_meeting_controller.rb b/app/controllers/mentor_meeting_controller.rb new file mode 100644 index 00000000000..c4ec017870f --- /dev/null +++ b/app/controllers/mentor_meeting_controller.rb @@ -0,0 +1,74 @@ +class MentorMeetingController < ApplicationController + include MentorMeetingsHelper + + before_action :set_team_and_meeting, only: [:edit_date, :delete_date] + + # Method to get meeting dates for a particular assignment + def get_dates + @mentor_meetings = MentorMeeting.all + render json: @mentor_meetings, status::ok + end + + # Method to add meetings dates to the mentor_meetings table. +def add_date + team_id = params[:team_id] + meeting_date = params[:meeting_date] + @mentor_meeting = MentorMeeting.create(team_id: team_id, meeting_date: meeting_date) + + if @mentor_meeting.save + MentorMeetingNotifications.send_notification(team_id, meeting_date) + render json: { status: 'success', message: "Meeting date added" } + else + render json: { status: 'error', message: "Unable to add meeting date" } + end +end + + + def edit_date + team_id = params[:team_id] + old_meeting_date = params[:old_date] + new_meeting_date = params[:new_date] + + @meeting = MentorMeeting.where(team_id: team_id.to_i, meeting_date: old_meeting_date).first + if @meeting + @meeting.meeting_date = new_meeting_date + if @meeting.save + # Trigger notification after editing + ActiveSupport::Notifications.instrument('mentor_meeting.updated', team_id: team_id, old_meeting_date: old_meeting_date, new_meeting_date: new_meeting_date) + render json: { status: 'success', message: 'Meeting updated successfully' } + else + render json: { status: 'error', message: 'Failed to update meeting' } + end + else + render json: { status: 'error', message: 'Meeting not found' } + end + end + + + def delete_date + team_id = params[:team_id] + meeting_date = params[:meeting_date] + @meeting = MentorMeeting.where(team_id: team_id.to_i, meeting_date: meeting_date).first + + if @meeting + @meeting.destroy + # Trigger notification after deletion + ActiveSupport::Notifications.instrument('mentor_meeting.deleted', team_id: team_id, meeting_date: meeting_date) + render json: { status: 'success', message: 'Meeting deleted successfully' } + else + render json: { status: 'error', message: 'Meeting not found' } + end + end + + private + + def meeting_dates_params #permitting parameters through the model + params.require(:meeting_dates).permit(:team_id, :date) + end + + def set_team_and_meeting #means by which a specific team meeting can be found based on its parameters + @meeting = MentorMeeting.find_by(team_id: params[:team_id].to_i, meeting_date: params[:meeting_date]) + render json: { status: 'error', message: 'Meeting not found' }, status: :not_found unless @meeting + end +end + diff --git a/app/controllers/teams_controller.rb b/app/controllers/teams_controller.rb index 1d2fd966a3d..055a7cc29ed 100644 --- a/app/controllers/teams_controller.rb +++ b/app/controllers/teams_controller.rb @@ -1,6 +1,7 @@ class TeamsController < ApplicationController include AuthorizationHelper - + include MentorMeetingsHelper + autocomplete :user, :name # Check if the current user has TA privileges @@ -53,6 +54,8 @@ def list unless @assignment.nil? if @assignment.auto_assign_mentor @model = MentoredTeam + # MentorMeeting.delete_all + @mentor_meetings = MentorMeeting.all else @model = AssignmentTeam end @@ -61,6 +64,8 @@ def list begin @root_node = Object.const_get(session[:team_type] + 'Node').find_by(node_object_id: params[:id]) @child_nodes = @root_node.get_teams + + @meetings_map = get_dates_for_team(@child_nodes) rescue StandardError flash[:error] = $ERROR_INFO end @@ -171,6 +176,20 @@ def copy_teams(operation) redirect_to controller: 'teams', action: 'list', id: assignment.id end + # Method to get meeting dates for a particular assignment + def get_mentor_meeting_dates + mentor_meetings = MentorMeeting.all # Or your query to fetch data + render json: mentor_meetings + end + + # Method to add meetings dates to the mentor_meetings table. + def add_mentor_meeting_date + team_id = params[:team_id] + meeting_date = params[:meeting_date] + MentorMeeting.create(team_id: team_id, meeting_date: meeting_date) + render :json => { :status => 'success', :message => "Ok"} + end + # Abstraction over different methods def choose_copy_type(assignment, operation) course = Course.find(assignment.course_id) diff --git a/app/helpers/mailer_helper.rb b/app/helpers/mailer_helper.rb index 568f35788c1..bc052d0aa81 100644 --- a/app/helpers/mailer_helper.rb +++ b/app/helpers/mailer_helper.rb @@ -14,6 +14,22 @@ def self.send_mail_to_user(user, subject, partial_name, password) ) end + def self.send_team_confirmation_mail_to_user(user, subject, partial_name, team_name, assignment_name) + # This function serves as a helper to send emails to users letting them know they have added to a team + # note that the below hash is sent to a view html that has the partial_name + Mailer.generic_message( + to: user.email, + subject: subject, + body: { + user: user, + first_name: ApplicationHelper.get_user_first_name(user), + partial_name: partial_name, + team: team_name, + assignment: assignment_name + } + ) + end + def self.send_mail_to_all_super_users(super_user, user, subject) Mailer.request_user_message( to: super_user.email, diff --git a/app/helpers/mentor_meetings_helper.rb b/app/helpers/mentor_meetings_helper.rb new file mode 100644 index 00000000000..4618be97634 --- /dev/null +++ b/app/helpers/mentor_meetings_helper.rb @@ -0,0 +1,14 @@ +module MentorMeetingsHelper + + def get_dates_for_team(children) + @meeting_map = {} + + children.each do |child| + team_id = child.node_object_id.to_i + @meeting_map[team_id] = MentorMeeting.where(team_id: team_id).pluck(:meeting_date) + end + + @meeting_map + end + +end diff --git a/app/mailers/mailer.rb b/app/mailers/mailer.rb index b96924fbf6c..4d4ccf1e3ef 100644 --- a/app/mailers/mailer.rb +++ b/app/mailers/mailer.rb @@ -24,7 +24,8 @@ def generic_message(defn) @avg_pct = defn[:body][:avg_pct] @assignment = defn[:body][:assignment] @conference_variable = defn[:body][:conference_variable] - + @team = defn[:body][:team] # team name + if Rails.env.development? || Rails.env.test? defn[:to] = 'expertiza.mailer@gmail.com' end diff --git a/app/models/mentor_meeting.rb b/app/models/mentor_meeting.rb new file mode 100644 index 00000000000..1281200e41b --- /dev/null +++ b/app/models/mentor_meeting.rb @@ -0,0 +1,5 @@ +class MentorMeeting < ApplicationRecord + def self.table + 'mentor_meetings' + end +end diff --git a/app/models/mentor_meeting_notifications.rb b/app/models/mentor_meeting_notifications.rb new file mode 100644 index 00000000000..4ee02f08588 --- /dev/null +++ b/app/models/mentor_meeting_notifications.rb @@ -0,0 +1,9 @@ +class MentorMeetingNotifications + def self.send_notification(team_id, meeting_date) + ActiveSupport::Notifications.instrument('mentor_meeting.created', team_id: team_id, meeting_date: meeting_date) + end +end + +ActiveSupport::Notifications.subscribe('mentor_meeting.created') do |name, start, finish, id, payload| + puts "New meeting created for team #{payload[:team_id]} on #{payload[:meeting_date]}" +end diff --git a/app/models/mentored_team.rb b/app/models/mentored_team.rb index daccd65d37d..a43feca21e7 100644 --- a/app/models/mentored_team.rb +++ b/app/models/mentored_team.rb @@ -12,7 +12,20 @@ def add_member(user, _assignment_id = nil) TeamUserNode.create(parent_id: parent.id, node_object_id: t_user.id) add_participant(parent_id, user) ExpertizaLogger.info LoggerMessage.new('Model:Team', user.name, "Added member to the team #{id}") + + assignment_name = _assignment_id ? Assignment.find(_assignment_id).name.to_s : "" + # mentor only + if MentorManagement.user_a_mentor?(user) && !user.is_a?(Participant) + MailerHelper.send_team_confirmation_mail_to_user(user, "[Expertiza] Added to a Team", "mentor_added_to_team", "#{name}", assignment_name).deliver + # participant only + elsif !MentorManagement.user_a_mentor?(user) && user.is_a?(Participant) + MailerHelper.send_team_confirmation_mail_to_user(user, "[Expertiza] Added to a Team", "user_added_to_team", "#{name}", assignment_name).deliver + # dual case + elsif MentorManagement.user_a_mentor?(user) && user.is_a?(Participant) + MailerHelper.send_team_confirmation_mail_to_user(user, "[Expertiza] Added to a Team", "dual_role_added_to_team", "#{name}", assignment_name).deliver + end end + if can_add_member MentorManagement.assign_mentor(_assignment_id, id) end diff --git a/app/models/team.rb b/app/models/team.rb index 9786c55431b..f2d4a06e210 100644 --- a/app/models/team.rb +++ b/app/models/team.rb @@ -88,6 +88,25 @@ def add_member(user, _assignment_id = nil) TeamUserNode.create(parent_id: parent.id, node_object_id: t_user.id) add_participant(parent_id, user) ExpertizaLogger.info LoggerMessage.new('Model:Team', user.name, "Added member to the team #{id}") + + # if assignment_id is nil, then don't send an assignment name + assignment_name = _assignment_id ? Assignment.find(_assignment_id).name.to_s : "" + + # addressing efg's comment in previous PR + # if just mentor + if MentorManagement.user_a_mentor?(user) && !user.is_a?(Participant) + MailerHelper.send_team_confirmation_mail_to_user(user, "[Expertiza] Added to a Team", "mentor_added_to_team", "#{name}", assignment_name).deliver + + # only a participant + elsif !MentorManagement.user_a_mentor?(user) && user.is_a?(Participant) + MailerHelper.send_team_confirmation_mail_to_user(user, "[Expertiza] Added to a Team", "user_added_to_team", "#{name}", assignment_name).deliver + + # both mentor and participant + elsif MentorManagement.user_a_mentor?(user) && user.is_a?(Participant) + MailerHelper.send_team_confirmation_mail_to_user(user, "[Expertiza] Added to a Team", "dual_role_added_to_team", "#{name}", assignment_name).deliver + + end + end can_add_member end diff --git a/app/models/user.rb b/app/models/user.rb index 38e80f15b36..2e0d8582f9d 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -324,3 +324,10 @@ def self.search_users(role, user_id, letter, search_by) users end end + + +def get_user_details(name) + user = User.where('name = ?', name).first +end + +public :get_user_details diff --git a/app/views/mailer/partials/_dual_role_added_to_team_html.html.erb b/app/views/mailer/partials/_dual_role_added_to_team_html.html.erb new file mode 100644 index 00000000000..e28a835e1c1 --- /dev/null +++ b/app/views/mailer/partials/_dual_role_added_to_team_html.html.erb @@ -0,0 +1,11 @@ +Hi <%= @first_name %>, +
+

+ You have been added to Team '<%= @team %>' for the Assignment '<%= @assignment %>' on Expertiza. +

+

+ Please note that you are assigned both as a mentor and a participant for this team. +

+

+ Expertiza Team +

diff --git a/app/views/mailer/partials/_mentor_added_to_team_html.html.erb b/app/views/mailer/partials/_mentor_added_to_team_html.html.erb new file mode 100644 index 00000000000..1fc320c8ec1 --- /dev/null +++ b/app/views/mailer/partials/_mentor_added_to_team_html.html.erb @@ -0,0 +1,8 @@ +Hi <%= @first_name %>, +
+

+ You are now mentoring Team '<%= @team %>' for the Assignment '<%= @assignment %>' on Expertiza. +

+

+ Expertiza Team +

diff --git a/app/views/mailer/partials/_mentor_added_to_team_plain.html.erb b/app/views/mailer/partials/_mentor_added_to_team_plain.html.erb new file mode 100644 index 00000000000..c943a3a8f3f --- /dev/null +++ b/app/views/mailer/partials/_mentor_added_to_team_plain.html.erb @@ -0,0 +1,5 @@ +Hi <%= @first_name %>, + +You are now mentoring Team '<%= @team %>' for the Assignment '<%= @assignment %>' on Expertiza. + +Expertiza Team diff --git a/app/views/mailer/partials/_user_added_to_team_html.html.erb b/app/views/mailer/partials/_user_added_to_team_html.html.erb new file mode 100644 index 00000000000..eb8e15d7df5 --- /dev/null +++ b/app/views/mailer/partials/_user_added_to_team_html.html.erb @@ -0,0 +1,8 @@ +Hi <%= @first_name %>, +
+

+ You have been added to Team '<%= @team %>' for the Assignment '<%= @assignment %>' on Expertiza. +

+

+ Expertiza Team +

diff --git a/app/views/mailer/partials/_user_added_to_team_plain.html.erb b/app/views/mailer/partials/_user_added_to_team_plain.html.erb new file mode 100644 index 00000000000..4ca128adf37 --- /dev/null +++ b/app/views/mailer/partials/_user_added_to_team_plain.html.erb @@ -0,0 +1,5 @@ +Hi <%= @first_name %>, + +You have been added to Team '<%= @team %>' for the Assignment '<%= @assignment %>' on Expertiza. + +Expertiza Team diff --git a/app/views/teams/_team.html.erb b/app/views/teams/_team.html.erb index a45b599012b..c2936e9ceb9 100644 --- a/app/views/teams/_team.html.erb +++ b/app/views/teams/_team.html.erb @@ -1,14 +1,21 @@ +<% if @model == MentoredTeam %> + <%= render :partial => '/tree_display/page_footer_assignments', :locals => { :assignment_id => @root_node.node_object_id, :@meeting_map => @meeting_map } %>
+<% else %> + <%= render :partial => '/tree_display/page_footer' %>
+ Show all team members <%= render :partial => '/tree_display/page_footer' %>
<% session[:return_to] = request.url %> <% @model %> + +

Team List

+
<%= link_to 'Create Team', :action => 'new', :id=> @root_node.node_object_id, :model => @model %> -<% if @root_node.class == AssignmentNode %> - <% modelType = 'AssignmentTeam' %> -<% else %> - <% modelType = 'CourseTeam' %> -<% end %> -| <%= link_to 'Import Teams', +<% modelType = @root_node.class == AssignmentNode ? 'AssignmentTeam' : 'CourseTeam' %> + +// reformat team actions +
+ <%= link_to 'Import Teams', :controller=>'import_file', :action=>'start', :model => modelType, @@ -22,4 +29,51 @@ :id=>@root_node.node_object_id %> |<%= link_to 'Delete All Teams', :action => 'delete_all', :id=> @root_node.node_object_id, :model => @model %> |<%= link_to 'Bequeath All Teams', :action=>'bequeath_all', :id => @root_node.node_object_id, :model => @model %> -|<%= render :partial => '/shared_scripts/back' %> +
+ +// additional functionality to include meeting dates and add the + button to add more meetings. +
+

Mentor Meeting Dates

+
+ <% @teams.each do |team| %> +
+

<%= team.name %>

+

Mentor: <%= team.mentor.name %>

+

Members: <%= team.members.map(&:name).join(', ') %>

+ +
+

Meeting Dates

+ <% team.meeting_dates.each do |date| %> +
+ /> + <% if current_user.instructor? || current_user == team.mentor %> //current team mentor and instructor can remove + + <% end %> +
+ <% end %> + +
+
+<% end %> + + + + + + diff --git a/app/views/tree_display/_entry_assignments.html.erb b/app/views/tree_display/_entry_assignments.html.erb new file mode 100644 index 00000000000..a3f778f0a72 --- /dev/null +++ b/app/views/tree_display/_entry_assignments.html.erb @@ -0,0 +1,243 @@ +<% + team_name = prefix.split('_').first + team_id = team_name.to_i +%> +<% + def find_date(team_id, index) + @meeting_map[team_id].length !=0 ? @meeting_map[team_id][index].to_s : '' + end +%> +<% child_nodes = node.get_children(@sortvar,@sortorder,session[:user].id,@show,@search) %> +<% + @student_full_names = [] + @student_email = [] + @student_names = [] + @student_count = 0 + @student_ids = [] + child_nodes.each_with_index do |child_node,index| + child_node_name = child_node.get_name(session[:ip]) + if child_node_name.include?("(Mentor)") + child_node_name = child_node_name.gsub(" (Mentor)", "") + end + @user = User.get_user_details(child_node_name) + @full_name = @user.fullname.gsub(/(\d+),\s*(\w+)/, '\2 \1') + if child_node.get_name(session[:ip]).include?("(Mentor)") + @ta_name = @full_name + @ta_username = @user.name + else + @student_full_names << @full_name + @student_email << @user.email + @student_names << @user.name + @student_ids << child_node.node_object_id + end + end + + @student_count = @student_names.length + while @student_names.length < 3 + @student_names << "" + end + @combined_full_names = @student_full_names.join(", ") + @combined_emails = @student_email.join(", ") +%> +<% + @can_edit = (session["user"].role_id == 2 or (session["user"].name == @ta_username)) +%> + +class="<%= rowtype %>" id="<%= prefix %>" + <% elsif prefix != nil %>id="<%= prefix %>" style="display: none;" name="team member" + <% end %> +> + + <%= team_name %> + + + <%= @combined_full_names %> + + <% @student_names.each_with_index do |name, idx| %> + <% if not name.empty? %> + <%= name %>
+ <%= link_to image_tag("delete_icon.png", :border=>0, :alt => "Delete Team User", :title => "Delete Team User"), :controller=>'teams_users', :action=>'delete', :id => @student_ids[idx] %> + + <% else + @can_edit = false + %> + + <% end %> + <% end %> + + <%= @combined_emails %> + + <% if @student_count == 3 %> + + <%= @ta_name %> + + <% else %> + + <% end %> + <%= render :partial => '/tree_display/actions/'+node.get_partial_name, + :locals => {:node => node} %> + <% + (1..@max_dates_length).each do |index| + %> + + > + + <% + end + %> + + + <%= image_tag("plus.png", :border=>0, :alt => "Add new date column", :title => "Add new date column") %> + + + + + diff --git a/app/views/tree_display/_page_footer_assignments.html.erb b/app/views/tree_display/_page_footer_assignments.html.erb new file mode 100644 index 00000000000..1391fb28b03 --- /dev/null +++ b/app/views/tree_display/_page_footer_assignments.html.erb @@ -0,0 +1,50 @@ +<% + max_dates_length = 0 + + @meeting_map.each_value do |value| + max_dates_length = value.length if value.length > max_dates_length + end + + if max_dates_length < 3 + max_dates_length = 3 + end +%> +<% if @child_nodes.length > 0 %> + + + + + + + + + + + + <% + (3..max_dates_length - 1).each do |index| + %> + + <% + end + %> + + + + <% + @child_nodes.each_with_index do |node,index| + if index.odd? + rowtype = "odd" + else + rowtype = "even" + end + %> + + + <%= render :partial=> '/tree_display/entry_assignments', :locals => {:search => @search, :node => node, :prefix => node.node_object_id.to_s+"_"+index.to_s, :depth => 0, :rowtype => rowtype, :assignment_id => assignment_id, :@meeting_map => @meeting_map, :@max_dates_length => max_dates_length} %> + + <% + end + %> +
+<% end %> diff --git a/config/routes.rb b/config/routes.rb index c2ae428631d..e573ebc667b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -664,5 +664,11 @@ post '/sample_reviews/unmap/:id' => 'sample_reviews#unmap_from_assignment' post 'student_task/publishing_rights_update', controller: :student_task, action: :publishing_rights_update, method: :put get 'student_view/flip_view', controller: :student_view, action: :flip_view + + get 'get_dates', controller: :mentor_meeting, action: :get_dates + post 'add_date', controller: :mentor_meeting, action: :add_date + patch 'edit_date', controller: :mentor_meeting, action: :edit_date + post 'delete_date', controller: :mentor_meeting, action: :delete_date + # updated route and added specific controller action upon accessing this route end diff --git a/db/migrate/20240318185959_create_mentor_meetings.rb b/db/migrate/20240318185959_create_mentor_meetings.rb new file mode 100644 index 00000000000..bf06e112232 --- /dev/null +++ b/db/migrate/20240318185959_create_mentor_meetings.rb @@ -0,0 +1,18 @@ +class CreateMentorMeetings < ActiveRecord::Migration[5.1] + def self.up + create_table :mentor_meetings do |t| + t.column :team_id, :integer, null: false + t.column :assignment_id, :integer, null: false + t.column :meeting_date, :string, null: false + end + + execute "ALTER TABLE `mentor_meetings` + ADD CONSTRAINT `fk_mentor_meetings_mapping_team` + FOREIGN KEY (team_id) references teams(id)" + + execute "ALTER TABLE `mentor_meetings` + ADD CONSTRAINT `fk_mentor_meetings_mapping_assignment` + FOREIGN KEY (assignment_id) references assignments(id)" + + end +end diff --git a/db/migrate/20240318200827_remove_assignment_id_from_mentor_meetings.rb b/db/migrate/20240318200827_remove_assignment_id_from_mentor_meetings.rb new file mode 100644 index 00000000000..e7d1c6a6911 --- /dev/null +++ b/db/migrate/20240318200827_remove_assignment_id_from_mentor_meetings.rb @@ -0,0 +1,9 @@ +class RemoveAssignmentIdFromMentorMeetings < ActiveRecord::Migration[5.1] + def up + # Remove the foreign key constraint + execute "ALTER TABLE `mentor_meetings` DROP FOREIGN KEY `fk_mentor_meetings_mapping_assignment`" + + # Remove the column + remove_column :mentor_meetings, :assignment_id + end +end diff --git a/spec/controllers/mentor_meeting_controller_spec.rb b/spec/controllers/mentor_meeting_controller_spec.rb new file mode 100644 index 00000000000..ce346c536e9 --- /dev/null +++ b/spec/controllers/mentor_meeting_controller_spec.rb @@ -0,0 +1,37 @@ +require 'rails_helper' + +RSpec.describe MentorMeetingController, type: :controller do + describe 'POST #add_date' do + it 'creates a new meeting date and triggers a notification' do + expect { + post :add_date, params: { team_id: 1, meeting_date: '2024-11-01' } + }.to change(MentorMeeting, :count).by(1) + + expect(response.status).to eq(200) + expect(JSON.parse(response.body)['status']).to eq('success') + end + end + + describe 'PATCH #edit_date' do + it 'updates the meeting date' do + mentor_meeting = MentorMeeting.create!(team_id: 1, meeting_date: '2024-11-01') + patch :edit_date, params: { team_id: 1, old_date: '2024-11-01', new_date: '2024-11-02' } + + expect(response.status).to eq(200) + expect(JSON.parse(response.body)['status']).to eq('success') + expect(mentor_meeting.reload.meeting_date).to eq('2024-11-02') + end + end + + describe 'DELETE #delete_date' do + it 'deletes the meeting date' do + mentor_meeting = MentorMeeting.create!(team_id: 1, meeting_date: '2024-11-01') + expect { + delete :delete_date, params: { team_id: 1, meeting_date: '2024-11-01' } + }.to change(MentorMeeting, :count).by(-1) + + expect(response.status).to eq(200) + expect(JSON.parse(response.body)['status']).to eq('success') + end + end +end diff --git a/spec/factories/factories.rb b/spec/factories/factories.rb index c359e784672..2765ebf380c 100644 --- a/spec/factories/factories.rb +++ b/spec/factories/factories.rb @@ -761,4 +761,10 @@ ta_id 1 course_id 1 end + +factory :meeting_date, class: MeetingDate do + date { Date.today } # Default to today's date + team # Assumes you have a team association set up + end + end diff --git a/spec/models/mentor_management_spec.rb b/spec/models/mentor_management_spec.rb index 1a818eafdb4..2df9240b480 100644 --- a/spec/models/mentor_management_spec.rb +++ b/spec/models/mentor_management_spec.rb @@ -1,3 +1,5 @@ +#require 'rails_helper' + describe MentorManagement do # using let! so that state is automatically set up before each example group # this could also be accomplished with before(:each) and instance methods @@ -165,6 +167,14 @@ # There should be no assigning of mentors expect(Team).to receive(:add_member).exactly(0).times end + + describe '#update_mentor_state' do + it 'does not assign if `auto_assign_mentor` is false' do + no_mentor_assignment = create(:assignment, auto_assign_mentor: false) + + expect(Team).not_to receive(:add_member) + MentorManagement.assign_mentor(no_mentor_assignment.id, team.id) + end end context 'when the assignment or team already have a topic' do diff --git a/spec/models/team_spec.rb b/spec/models/team_spec.rb index 146d3e6bfea..c7adab57cc6 100644 --- a/spec/models/team_spec.rb +++ b/spec/models/team_spec.rb @@ -97,14 +97,45 @@ context 'when parameterized user did not join in current team yet' do context 'when current team is not full' do - it 'does not raise an error' do + before do allow_any_instance_of(Team).to receive(:user?).with(user).and_return(false) allow_any_instance_of(Team).to receive(:full?).and_return(false) allow(TeamsUser).to receive(:create).with(user_id: 1, team_id: 1).and_return(team_user) allow(TeamNode).to receive(:find_by).with(node_object_id: 1).and_return(double('TeamNode', id: 1)) allow_any_instance_of(Team).to receive(:add_participant).with(1, user).and_return(double('Participant')) + end + + it 'sends mail to mentor if user is a mentor' do + allow(MentorManagement).to receive(:user_a_mentor?).with(user).and_return(true) + allow(Assignment).to receive(:find).with(1).and_return(assignment) + allow(MailerHelper).to receive(:send_team_confirmation_mail_to_user).and_return(double('Mail', deliver: true)) + + expect(MailerHelper).to receive(:send_team_confirmation_mail_to_user).with(user, "[Expertiza] Added to a Team", "mentor_added_to_team", "#{team.name}", "").and_return(double('Mail', deliver: true)) + + expect(team.add_member(user)).to be true + end + + it 'sends mail to user if the user is a participant only' do + allow(MentorManagement).to receive(:user_a_mentor?).with(user).and_return(false) + allow(Assignment).to receive(:find).with(1).and_return(assignment) + allow(MailerHelper).to receive(:send_team_confirmation_mail_to_user).and_return(double('Mail', deliver: true)) + + expect(MailerHelper).to receive(:send_team_confirmation_mail_to_user).with(user, "[Expertiza] Added to a Team", "user_added_to_team", "#{team.name}", "").and_return(double('Mail', deliver: true)) + expect(team.add_member(user)).to be true + + end + + it 'sends dual-role mail if the user is both a mentor and a participant' do + allow(MentorManagement).to receive(:user_a_mentor?).with(user).and_return(true) + allow(user).to receive(:is_a?).with(Participant).and_return(true) + allow(Assignment).to receive(:find).with(1).and_return(assignment) + allow(MailerHelper).to receive(:send_team_confirmation_mail_to_user).and_return(double('Mail', deliver: true)) + + expect(MailerHelper).to receive(:send_team_confirmation_mail_to_user).with(user, "[Expertiza] Added to a Team", "dual_role_added_to_team", "#{team.name}", "").and_return(double('Mail', deliver: true)) + expect(team.add_member(user)).to be true end + end end end