Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

E2479_Reimplement teams_users_controller.rb #146

Open
wants to merge 19 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
9ce86f3
Created teams_participants_controller.rb file
manideepika21 Nov 25, 2024
a397851
Created teams_participants view folder and added _form.html.erb
manideepika21 Nov 25, 2024
178579c
Added html files to teams_participants views folder
manideepika21 Nov 25, 2024
80963e7
Modified teams_users model name to teams_participants
manideepika21 Nov 25, 2024
4dbe244
Updated teams_participants_controller
Nov 29, 2024
88af789
Moved logic of adding and removing team members to teams model
Nov 29, 2024
bcd4802
Moved logic of adding/removing user to/from a team to teams_participa…
Nov 29, 2024
22cdee9
Moved teams model from expertiza to reimplementation-back-end repository
manideepika21 Nov 30, 2024
a553435
Moved teams_users model from expertiza to reimplementation-back-end r…
manideepika21 Nov 30, 2024
638ed31
modified assignments model to move the assignment specific methods to…
Dec 3, 2024
2d4b980
modified course model to move the course specific methods to this model
Dec 3, 2024
f97c630
modified teams participants model to move the teams participants meth…
Dec 3, 2024
c3893ef
Modified teams_users_controller to adhere to DRY principles and refa…
manideepika21 Dec 3, 2024
8932286
Resolved merge conflicts in teams_participants_controller, teams mode…
manideepika21 Dec 3, 2024
52fdca5
Changed the variable names and added comments
manideepika21 Dec 4, 2024
4f3b308
Added spec file to test the teams_participants_controller
manideepika21 Dec 4, 2024
e6b39e7
Changed the function name in assignment model
manideepika21 Dec 4, 2024
98eeee3
Added logic to check if the user is already in the team
manideepika21 Dec 4, 2024
51af1cc
Modified variable names in teams_participants_controller
manideepika21 Dec 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 149 additions & 0 deletions app/controllers/api/v1/teams_participants_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
class Api::V1::TeamsParticipantsController < ApplicationController
include AuthorizationHelper

# Determines if the current user is allowed to perform the requested action.
def action_allowed?
if %w[update_duties].include? params[:action]
current_user_has_student_privileges?
else
current_user_has_ta_privileges?
end
end

# Fetches and renders an auto-complete list of possible team members based on a partial name input.
def auto_complete_for_participant_name
# Fetch the current team using the session-stored `team_id`.
current_team = Team.find(session[:team_id])

# Fetch potential members for the team based on the input name.
@potential_team_members = current_team.get_possible_team_members(params[:user][:name])

# Render the autocomplete suggestions.
render inline: "<%= auto_complete_result @potential_team_members, 'name' %>", layout: false
end

# Updates the duty (role) assigned to a participant in a team.
def update_duties
# Find the team member relationship using the provided ID.
team_member_relationship = TeamsUser.find(params[:teams_user_id])

# Update the duty of the team member.
team_member_relationship.update_attribute(:duty_id, params[:teams_user]['duty_id'])

# Redirect to the participant's team view page.
redirect_to controller: 'student_teams', action: 'view', student_id: params[:participant_id]
end

# Displays a paginated list of all participants in a specific team.
def list_participants
# Fetch the team based on the provided ID.
current_team = Team.find(params[:id])

# Retrieve the associated assignment or course for the team.
associated_assignment_or_course = Assignment.find(current_team.parent_id)

# Query and paginate participants of the current team.
@team_participants = TeamsUser.page(params[:page]).per_page(10).where(team_id: current_team.id)

@team = current_team
@assignment = associated_assignment_or_course
end

# Renders the form for adding a new participant to a team.
def add_new_participant
# Fetch the team for which a participant is to be added.
@team = Team.find(params[:id])
end
#Deletes the selected participant
def delete_selected_participant
@teams_user = TeamsUser.find(params[:id])
parent_id = Team.find(@teams_user.team_id).parent_id
@user = User.find(@teams_user.user_id)
@teams_user.destroy
undo_link("The team user \"#{@user.name}\" has been successfully removed. ")
redirect_to controller: 'teams', action: 'list', id: parent_id
end

# Adds a new participant to a team after validation.
def create_participant
# Find the user by their name from the input.
find_participant = find_participant_by_name
# Fetch the team using the provided ID.
current_team = find_team_by_id
if validate_participant_and_team(participant, team)
if team.add_participants_with_validation(participant, team.parent_id)
undo_link("The participant \"#{participant.name}\" has been successfully added to \"#{team.name}\".")
else
flash[:error] = 'This team already has the maximum number of members.'
end
end
# Redirect to the list of teams for the parent assignment or course.
redirect_to controller: 'teams', action: 'list', id: current_team.parent_id
end

private

# Helper method to find a user by their name.
def find_participant_by_name
# Locate the user by their name.
find_participant = User.find_by(name: params[:user][:name].strip)

# Display an error if the user is not found.
unless find_participant
flash[:error] = participant_not_found_error
redirect_back fallback_location: root_path
end
participant
end

# Helper method to fetch a team by its ID.
def find_team_by_id
Team.find(params[:id])
end

# Validates whether a participant can be added to the given team.
def validate_participant_and_team(participant, team)
# Check if the participant is valid for the team type.
validation_result = if team.is_a?(AssignmentTeam)
Assignment.find(team.parent_id).valid_team_participant?(participant)
else
Course.find(team.parent_id).valid_team_participant?(participant)
end

# Handle validation errors if any.
if validation_result[:success]
true
else
flash[:error] = validation_result[:error]
redirect_back fallback_location: root_path
false
end
end

# Adds the participant to the team while handling constraints.
def add_participant_to_team(find_participant, team)
# Add the participant to the team and handle the outcome.
addition_result = find_team_by_id.add_participant(find_participant, team.parent_id)
process_participant_addition_result(find_participant, team, addition_result)
end

# Handles the result of adding a participant to the team.
def process_participant_addition_result(find_participant, team, addition_result)
if addition_result == false
flash[:error] = 'This team already has the maximum number of members.'
else
undo_link("The team user \"#{find_participant.name}\" has been successfully added to \"#{team.name}\".")
end
end

# Generates an error message when a user is not found.
def participant_not_found_error
new_participnat_url = url_for controller: 'users', action: 'new'
"\"#{params[:user][:name].strip}\" is not defined. Please <a href=\"#{new_participant_url}\">create</a> this user before continuing."
end

def non_participant_error(find_participant, parent_id, model)
urlParticipantList = url_for controller: 'participants', action: 'list', id: parent_id, model: model, authorization: 'participant'
"\"#{find_participant.name}\" is not a participant of the current course/assignment. Please <a href=\"#{urlParticipantList}\">add</a> this user before continuing."
end
end
47 changes: 39 additions & 8 deletions app/models/assignment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class Assignment < ApplicationRecord
has_many :sign_up_topics , class_name: 'SignUpTopic', foreign_key: 'assignment_id', dependent: :destroy
belongs_to :course, optional: true
belongs_to :instructor, class_name: 'User', inverse_of: :assignments
validates :max_team_size, numericality: { only_integer: true, greater_than_or_equal_to: 1 }, allow_nil: true

#This method return the value of the has_badge field for the given assignment object.
attr_accessor :title, :description, :has_badge, :enable_pair_programming, :is_calibrated, :staggered_deadline
Expand All @@ -22,10 +23,11 @@ def review_questionnaire_id
def teams?
@has_teams ||= teams.any?
end

def num_review_rounds
rounds_of_reviews
end

# Add a participant to the assignment based on the provided user_id.
# This method first finds the User with the given user_id. If the user does not exist, it raises an error.
# It then checks if the user is already a participant in the assignment. If so, it raises an error.
Expand Down Expand Up @@ -79,8 +81,6 @@ def remove_assignment_from_course
self
end



# Assign a course to the assignment based on the provided course_id.
# If the assignment already belongs to the specified course, an error is raised.
# Returns the modified assignment object with the updated course assignment.
Expand All @@ -98,7 +98,6 @@ def assign_course(course_id)
assignment
end


# Create a copy of the assignment, including its name, instructor, and course assignment.
# The new assignment is named "Copy of [original assignment name]".
# Returns the newly created assignment object, which is a copy of the original assignment.
Expand All @@ -117,6 +116,7 @@ def copy
copied_assignment

end

def is_calibrated?
is_calibrated
end
Expand All @@ -133,7 +133,6 @@ def staggered_and_no_topic?(topic_id)
staggered_deadline? && topic_id.nil?
end


#This method return the value of the has_topics field for the given assignment object.
# has_topics is of boolean type and is set true if there is any topic associated with the assignment.
def topics?
Expand Down Expand Up @@ -183,7 +182,6 @@ def valid_num_review(review_type)
end
end


#This method check if for the given assignment,different type of rubrics are used in different round.
# Checks if for the given assignment any questionnaire is present with used_in_round field not nil.
# Returns a bolean value whether such questionnaire is present.
Expand All @@ -192,7 +190,40 @@ def varying_rubrics_by_round?
# Check if any rubric has a specified round
rubric_with_round.present?
end



#E2479
#check if the user is on the team
def user_on_team?(user)
teams = self.teams
users = []
teams.each do |team|
users << team.users
end
users.flatten.include? user
end
# Validates if a user is eligible to join a team for the current assignment.
# This method ensures that:
# - The user is not already part of another team for this assignment.
# - The user is a valid participant in the assignment.
# Params:
# - user: The user to validate for team membership.
# Returns:
# - A hash indicating the validation result:
# - { success: true } if the user can join the team.
# - { success: false, error: "Reason for failure" } if the user cannot join the team.
def valid_team_participant?(user)
# Check if the user is already part of a team for this assignment.
if user_on_team?(user)
{ success: false, error: "This user is already assigned to a team for this assignment" }

# Check if the user is a registered participant in the assignment.
elsif AssignmentParticipant.find_by(user_id: user.id, parent_id: assignment_id).nil?
{ success: false, error: "#{user.name} is not a participant in this assignment" }

# If both checks pass, the user is eligible to join the team.
else
{ success: true }
end
end

end
9 changes: 8 additions & 1 deletion app/models/assignment_participant.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ class AssignmentParticipant < Participant
belongs_to :user
validates :handle, presence: true


def set_handle
self.handle = if user.handle.nil? || (user.handle == '')
user.name
Expand All @@ -16,5 +15,13 @@ def set_handle
end
self.save
end
#E2479
def team
AssignmentTeam.team(self)
end

def team_user
TeamsUser.where(team_id: team.id, user_id: user_id).first if team
end

end
37 changes: 36 additions & 1 deletion app/models/course.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def path
raise 'Path can not be created as the course must be associated with an instructor.' if instructor_id.nil?
Rails.root + '/' + Institution.find(institution_id).name.gsub(" ", "") + '/' + User.find(instructor_id).name.gsub(" ", "") + '/' + directory_path + '/'
end

# Add a Teaching Assistant to the course
def add_ta(user)
if user.nil?
Expand Down Expand Up @@ -49,4 +49,39 @@ def copy_course
new_course.name += '_copy'
new_course.save
end
#E2479
#checks if the user is in the team
def user_on_team?(user)
teams = self.teams
users = []
teams.each do |team|
users << team.users
end
users.flatten.include? user
end
# Checks if a user is eligible to join a specific team for a course.
# This method ensures that:
# - The user is not already a member of another team for the course.
# - The user is a valid participant in the course.
# Params:
# - user: The user to be validated for team membership.
# Returns:
# - A hash indicating success or failure:
# - { success: true } if the user can be added to the team.
# - { success: false, error: "Reason for failure" } if the user cannot be added.
def valid_team_participant?(user)
# Check if the user is already a member of another team for the same course.
if user_on_team?(user)
{ success: false, error: "This user is already assigned to a team for this course" }

# Check if the user is a participant in the course associated with this team.
elsif CourseParticipant.find_by(user_id: user.id, parent_id: course_id).nil?
{ success: false, error: "#{user.name} is not a participant in this course" }

# If both checks pass, the user is eligible to join the team.
else
{ success: true }
end
end

end
35 changes: 35 additions & 0 deletions app/models/course_participant.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
class CourseParticipant < Participant
belongs_to :course, class_name: 'Course', foreign_key: 'parent_id'

# Copy this participant to an assignment
def copy_to_assignment(assignment_id)
part = AssignmentParticipant.find_or_create_by(user_id: user_id, parent_id: assignment_id)
part.set_handle if part.persisted?
part
end

# Provide import functionality for Course Participants
def self.import(row_hash, session, course_id)
raise ArgumentError, 'No user ID has been specified.' if row_hash.empty?

user = User.find_by(name: row_hash[:username])
unless user
raise ArgumentError, "The record containing #{row_hash[:username]} does not have enough items." if row_hash.length < 4

attributes = ImportFileHelper.define_attributes(row_hash)
user = ImportFileHelper.create_new_user(attributes, session)
end

course = Course.find(course_id)
raise ImportError, "The course with the ID #{course_id} was not found." unless course

unless exists?(user_id: user.id, parent_id: course_id)
create(user_id: user.id, parent_id: course_id)
end
end

# Generate a path for this participant
def path
course.path.join(directory_num.to_s)
end
end
Loading