Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
Empty file added 2
Empty file.
94 changes: 94 additions & 0 deletions app/controllers/api/v1/submission_records_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
class SubmissionRecordsController < ApplicationController
include AuthorizationHelper

# Set up before_action callbacks
before_action :set_submission_record, only: %i[show edit update destroy]
before_action :set_assignment_team, only: [:index]
rescue_from ActiveRecord::RecordNotFound, with: :not_found

# Determines if the current user has permission to access submission records
# Returns true for:
# - Administrators
# - Instructors teaching the assignment
# - TAs assigned to the assignment
# - Students who are members of the team
def action_allowed?
# Allow access to instructors, TAs, and admins
return true if current_user_has_admin_privileges?
return true if current_user_has_instructor_privileges? && current_user_instructs_assignment?(@assignment)
return true if current_user_has_ta_privileges? && current_user_has_ta_mapping_for_assignment?(@assignment)

# Allow students to view their own team's submission records
if current_user_has_student_privileges? && (@assignment_team.user_id == current_user.id || @assignment_team.users.include?(current_user))
return true
end

false
end

# Displays submission records for a specific assignment team
# - Fetches all records for the team
# - Orders them by most recent first
# - Makes them available to the view as @submission_records
def index
@submission_records = SubmissionRecord.where(team_id: @assignment_team.id)
.order(created_at: :desc) # Order by most recent first
render json: @submission_records, status: :ok
rescue StandardError => e
render json: { error: e.message }, status: :unprocessable_entity
end

# GET /submission_records/:id
def show
render json: @submission_record, status: :ok
end

# POST /submission_records
def create
@submission_record = SubmissionRecord.new(submission_record_params)
if @submission_record.save
render json: @submission_record, status: :created
else
render json: @submission_record.errors, status: :unprocessable_entity
end
end

# PATCH/PUT /submission_records/:id
def update
if @submission_record.update(submission_record_params)
render json: @submission_record, status: :ok
else
render json: @submission_record.errors, status: :unprocessable_entity
end
end

# DELETE /submission_records/:id
def destroy
@submission_record.destroy
render json: { message: 'Submission record deleted successfully' }, status: :no_content
end

private

# Sets up the assignment team and assignment for the current request
# Used by the index action to ensure proper context for viewing records
def set_assignment_team
@assignment_team = AssignmentTeam.find(params[:team_id])
@assignment = @assignment_team.parent
rescue ActiveRecord::RecordNotFound
render json: { error: 'Assignment team not found' }, status: :not_found
end

# Sets up a single submission record for show/edit/update/destroy actions
def set_submission_record
@submission_record = SubmissionRecord.find(params[:id])
end

def submission_record_params
params.require(:submission_record).permit(:team_id, :operation, :user, :content, :created_at)
end

def not_found
render json: { error: 'Submission record not found' }, status: :not_found
end
end
20 changes: 20 additions & 0 deletions app/models/submission_record.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Represents a record of a submission made by a student team
# This model tracks all submission activities
class SubmissionRecord < ApplicationRecord
# Associations
belongs_to :user
belongs_to :team, class_name: 'AssignmentTeam'
belongs_to :assignment

# Validations
validates :content, presence: true
validates :operation, presence: true
validates :team_id, presence: true
validates :user, presence: true
validates :assignment_id, presence: true

# Scopes for common queries
scope :recent, -> { order(created_at: :desc) }
scope :for_team, ->(team_id) { where(team_id: team_id) }
scope :for_assignment, ->(assignment_id) { where(assignment_id: assignment_id) }
end
154 changes: 154 additions & 0 deletions app/views/student_task/list.html.erb.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
<h1><%=t ".assignments" %></h1>


<div style="">
<div class="taskbox" style="width:18%; display: inline; float:left; margin-right: 10px;" >
<strong>&nbsp;&nbsp;<span class="tasknum">&nbsp;<%= @tasknotstarted.size.to_s %>&nbsp;</span> <%=t ".tasks_not_started" %><br></strong><br>

<% @tasknotstarted.each do |student_task|
participant = student_task.participant
stage = student_task.current_stage
controller = ""
action = ""
if stage == "submission" || stage == 'signup'
controller = "submitted_content"
action = "edit"

# check if the assignment has a sign-up sheet
if Assignment.find(participant.assignment.id).topics?
selected_topics = nil

#ACS Get the topics selected by all teams
#removed code that handles team and individual assignments differently
# get the user's team and check if they have signed up for a topic yet
users_team = Team.find_team_users(participant.assignment.id,participant.user.id)
if users_team.size > 0
selected_topics = SignedUpTeam.find_user_signup_topics(participant.assignment.id,users_team[0].t_id)
end

if selected_topics.nil? || selected_topics.length == 0
# there is a signup sheet and user/team hasn't signed up yet, produce a link to do so
controller = "sign_up_sheet"
action = "list"
end
end
elsif stage == "review" or stage == "metareview"
assignment = Assignment.find(participant.assignment.id)
if assignment.bidding_for_reviews_enabled == 'Bidding' and assignment.can_choose_topic_to_review?
controller = "review_bids"
action = "show"
elsif assignment.bidding_for_reviews_enabled == 'Bidding'
controller = "review_bids"
action = "index"
else
controller = "student_review"
action = "list"
end
end
%>

<span>&nbsp; &raquo;
<%= link_to student_task.assignment.name + " " + student_task.current_stage, :controller => controller, :action => action, :id => participant.id %>
(<%= student_task.relative_deadline %> <%=t ".left" %>)
</span><br/>
<% end %>

<br/> <strong> &nbsp;&nbsp;<span class="revnum">&nbsp;<%= @taskrevisions.size.to_s %>&nbsp;</span> <%=t ".revisions" %><br></strong><br>
<% @taskrevisions.each do |student_task|
participant = student_task.participant
stage = student_task.current_stage
topic_id = SignedUpTeam.topic_id(participant.parent_id, participant.user_id)
duedate = participant.assignment.stage_deadline(topic_id)
controller = ""
action = ""
if stage == "submission"
controller = "submitted_content"
action = "edit"
elsif stage == "review" or stage == "metareview"
controller = "student_review"
action = "list"
end
%>

<span>&nbsp; &raquo; <%= link_to participant.assignment.name + " " +
stage, :controller => controller, :action => action, :id => participant.id %>
(<%= time_ago_in_words(duedate) %> left) </span><br/>
<% end %>
<br/>

<strong><%=t ".student_team" %><br></strong><br>

<% @students_teamed_with.keys.each do |course_id| %>
<strong>&nbsp;&nbsp;<span class="tasknum">&nbsp;<%= @students_teamed_with[course_id].size.to_s %>&nbsp;</span>
<%if course_id.nil?%>
<%=t ".not_associated" %>
<%else%>
<%= Course.find(course_id).name %>
<%end%>
<br></strong><br>
<% if @students_teamed_with[course_id].size %>
<% @students_teamed_with[course_id].each do |student|%>
<span class="notification">&nbsp; &raquo; <%= student %> </span><br/>
<% end %>
<% end %>
<% end %>
</div>
<div class="topictable" style="float: left;width: 80%;margin-bottom: 10px; display: inline; ">
<table class="table table-striped" cellpadding="2">
<tr class="taskheader">
<th><%=t ".assignment_name" %></th>
<th><%=t ".course" %></th>
<th><%=t ".topic" %></th>
<th><%=t ".current_stage" %></th>
<th><%=t ".review_grade" %></th>
<th><%=t ".badges" %></th>
<th><%=t ".stage_deadline" %><img src="/assets/info.png" title="You can change 'Preferred Time Zone' in 'Profile' in the banner."/></th>
<th><%=t ".submission_history" %></th>
<th><%=t ".publishing_rights" %><img src="/assets/info.png" title="Grant publishing rights"/></th>
</tr>
<% @student_tasks.each do |student_task| %>
<% participant = student_task.participant %>
<% if student_task.assignment %>
<tr class="listingRow">
<!--assignment-->
<td><b><%= link_to student_task.assignment.name, :action => 'view', :id => participant %></b></td>
<!--course-->
<td><%= student_task.course.try :name %></td>
<!--topic-->
<% topic_id = SignedUpTeam.topic_id(participant.parent_id, participant.user_id) %>
<% if SignUpTopic.exists?(topic_id) %>
<td><%= SignUpTopic.find(topic_id).try :topic_name %></td>
<% else %>
<td>-</td>
<% end %>
<!--current stage-->
<td>
<% if participant.assignment.link_for_current_stage(topic_id)!= nil && participant.assignment.link_for_current_stage(topic_id).length!=0%>
<%= link_to participant.assignment.current_stage_name(topic_id), participant.assignment.link_for_current_stage(topic_id) %>
<% else %>
<%= participant.assignment.current_stage_name(topic_id) %>
<% end %>
</td>
<!--review grade-->

<td><%= get_review_grade_info(participant) %></td>
<!--badges-->
<td><%= get_awarded_badges(participant) %></td>
<!--stage deadline-->
<td><%= student_task.stage_deadline.in_time_zone(session[:user].timezonepref) %></td>
<!--publish rights-->
<td>
<%= link_to "Submission History", submission_records_path(team_id: participant.team.id) %>
</td>


<td align=center>
<input class='make-permit-change' id="<%= participant.id %>" type="checkbox" <% if participant.permission_granted %>checked<%end%>>
</td>

</tr>
<% end %>
<% end %>
</table>
</div>
</div>
26 changes: 26 additions & 0 deletions app/views/submission_records/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<h1>Submission History</h1>

<% if @submission_records.any? %>
<table class="table table-striped">
<thead>
<tr>
<th>Submission ID</th>
<th>Submitted By</th>
<th>Submission Time</th>
<th>Content</th>
</tr>
</thead>
<tbody>
<% @submission_records.each do |record| %>
<tr>
<td><%= record.id %></td>
<td><%= record.user.try(:name) || "Unknown" %></td>
<td><%= record.created_at.strftime("%Y-%m-%d %H:%M:%S") %></td>
<td><%= truncate(record.content, length: 50) %></td>
</tr>
<% end %>
</tbody>
</table>
<% else %>
<p>No submission records found for this team.</p>
<% end %>
47 changes: 42 additions & 5 deletions config/database.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,55 @@
# MySQL. Versions 5.5.8 and up are supported.
#
# Install the MySQL driver
# gem install mysql2
#
# Ensure the MySQL gem is defined in your Gemfile
# gem "mysql2"
#
# And be sure to use new-style password hashing:
# https://dev.mysql.com/doc/refman/5.7/en/password-hashing.html
#
default: &default
adapter: mysql2
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
port: 3306
socket: /var/run/mysqld/mysqld.sock
username: root
password: expertiza


development:
<<: *default
url: <%= ENV['DATABASE_URL'].gsub('?', '_development?') %>
database: reimplementation_development

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
<<: *default
url: <%= ENV['DATABASE_URL'].gsub('?', '_test?') %>
database: reimplementation_test

# As with config/credentials.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Instead, provide the password or a full connection URL as an environment
# variable when you boot the app. For example:
#
# DATABASE_URL="mysql2://myuser:mypass@localhost/somedatabase"
#
# If the connection URL is provided in the special DATABASE_URL environment
# variable, Rails will automatically merge its configuration values on top of
# the values provided in this file. Alternatively, you can specify a connection
# URL environment variable explicitly:
#
# production:
# url: <%= ENV["MY_APP_DATABASE_URL"] %>
#
# Read https://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full overview on how database connection configuration can be specified.
#
production:
<<: *default
url: <%= ENV['DATABASE_URL'].gsub('?', '_production?') %>
database: reimplementation_production
username: reimplementation
password: <%= ENV["REIMPLEMENTATION_DATABASE_PASSWORD"] %>
Loading