587 lines
26 KiB
Ruby
587 lines
26 KiB
Ruby
#
|
|
# Copyright (C) 2011 - present Instructure, Inc.
|
|
#
|
|
# This file is part of Canvas.
|
|
#
|
|
# Canvas is free software: you can redistribute it and/or modify it under
|
|
# the terms of the GNU Affero General Public License as published by the Free
|
|
# Software Foundation, version 3 of the License.
|
|
#
|
|
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
# details.
|
|
#
|
|
# You should have received a copy of the GNU Affero General Public License along
|
|
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
|
|
# @API Assignments
|
|
class AssignmentsController < ApplicationController
|
|
include Api::V1::Section
|
|
include Api::V1::Assignment
|
|
include Api::V1::AssignmentOverride
|
|
include Api::V1::AssignmentGroup
|
|
include Api::V1::Outcome
|
|
include Api::V1::ExternalTools
|
|
|
|
include KalturaHelper
|
|
include SyllabusHelper
|
|
before_action :require_context
|
|
add_crumb(proc { t '#crumbs.assignments', "Assignments" }, :except => [:destroy, :syllabus, :index]) { |c| c.send :course_assignments_path, c.instance_variable_get("@context") }
|
|
before_action { |c| c.active_tab = "assignments" }
|
|
before_action :normalize_title_param, :only => [:new, :edit]
|
|
|
|
def index
|
|
return redirect_to(dashboard_url) if @context == @current_user
|
|
|
|
if authorized_action(@context, @current_user, :read)
|
|
return unless tab_enabled?(@context.class::TAB_ASSIGNMENTS)
|
|
log_asset_access([ "assignments", @context ], 'assignments', 'other')
|
|
|
|
add_crumb(t('#crumbs.assignments', "Assignments"), named_context_url(@context, :context_assignments_url))
|
|
|
|
max_name_length_required_for_account = AssignmentUtil.name_length_required_for_account?(@context)
|
|
max_name_length = AssignmentUtil.assignment_max_name_length(@context)
|
|
sis_name = AssignmentUtil.post_to_sis_friendly_name(@context)
|
|
due_date_required_for_account = AssignmentUtil.due_date_required_for_account?(@context)
|
|
sis_integration_settings_enabled = AssignmentUtil.sis_integration_settings_enabled?(@context)
|
|
|
|
# It'd be nice to do this as an after_create, but it's not that simple
|
|
# because of course import/copy.
|
|
@context.require_assignment_group
|
|
set_js_assignment_data # in application_controller.rb, because the assignments page can be shared with the course home
|
|
|
|
set_tutorial_js_env
|
|
hash = {
|
|
WEIGHT_FINAL_GRADES: @context.apply_group_weights?,
|
|
POST_TO_SIS_DEFAULT: Assignment.sis_grade_export_enabled?(@context),
|
|
SIS_INTEGRATION_SETTINGS_ENABLED: sis_integration_settings_enabled,
|
|
SIS_NAME: sis_name,
|
|
MAX_NAME_LENGTH_REQUIRED_FOR_ACCOUNT: max_name_length_required_for_account,
|
|
MAX_NAME_LENGTH: max_name_length,
|
|
HAS_ASSIGNMENTS: @context.active_assignments.count > 0,
|
|
QUIZ_LTI_ENABLED: @context.quiz_lti_tool.present?,
|
|
DUE_DATE_REQUIRED_FOR_ACCOUNT: due_date_required_for_account,
|
|
}
|
|
js_env(hash)
|
|
|
|
respond_to do |format|
|
|
format.html do
|
|
@padless = true
|
|
render :new_index
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def show
|
|
rce_js_env(:highrisk)
|
|
@assignment ||= @context.assignments.find(params[:id])
|
|
if @assignment.deleted?
|
|
respond_to do |format|
|
|
flash[:notice] = t 'notices.assignment_delete', "This assignment has been deleted"
|
|
format.html { redirect_to named_context_url(@context, :context_assignments_url) }
|
|
end
|
|
return
|
|
end
|
|
if authorized_action(@assignment, @current_user, :read)
|
|
if @current_user && @assignment && !@assignment.visible_to_user?(@current_user)
|
|
respond_to do |format|
|
|
flash[:error] = t 'notices.assignment_not_available', "The assignment you requested is not available to your course section."
|
|
format.html { redirect_to named_context_url(@context, :context_assignments_url) }
|
|
end
|
|
return
|
|
end
|
|
|
|
@assignment = AssignmentOverrideApplicator.assignment_overridden_for(@assignment, @current_user)
|
|
@assignment.ensure_assignment_group
|
|
|
|
@locked = @assignment.locked_for?(@current_user, :check_policies => true, :deep_check_if_needed => true)
|
|
@locked.delete(:lock_at) if @locked.is_a?(Hash) && @locked.has_key?(:unlock_at) # removed to allow proper translation on show page
|
|
@unlocked = !@locked || @assignment.grants_right?(@current_user, session, :update)
|
|
|
|
unless @assignment.new_record? || (@locked && !@locked[:can_view])
|
|
@assignment.context_module_action(@current_user, :read)
|
|
end
|
|
|
|
if @assignment.grants_right?(@current_user, session, :read_own_submission) && @context.grants_right?(@current_user, session, :read_grades)
|
|
@current_user_submission = @assignment.submissions.where(user_id: @current_user).first if @current_user
|
|
@current_user_submission = nil if @current_user_submission &&
|
|
!@current_user_submission.graded? &&
|
|
!@current_user_submission.submission_type
|
|
@current_user_submission.send_later(:context_module_action) if @current_user_submission
|
|
end
|
|
|
|
log_asset_access(@assignment, "assignments", @assignment.assignment_group)
|
|
|
|
if request.format.html?
|
|
if @assignment.quiz?
|
|
return redirect_to named_context_url(@context, :context_quiz_url, @assignment.quiz.id)
|
|
elsif @assignment.discussion_topic? &&
|
|
@assignment.discussion_topic.grants_right?(@current_user, session, :read)
|
|
return redirect_to named_context_url(@context, :context_discussion_topic_url, @assignment.discussion_topic.id)
|
|
elsif @context.feature_enabled?(:conditional_release) && @assignment.wiki_page? &&
|
|
@assignment.wiki_page.grants_right?(@current_user, session, :read)
|
|
return redirect_to named_context_url(@context, :context_wiki_page_url, @assignment.wiki_page.id)
|
|
elsif @assignment.submission_types == 'external_tool' && @assignment.external_tool_tag && @unlocked
|
|
tag_type = params[:module_item_id].present? ? :modules : :assignments
|
|
return content_tag_redirect(@context, @assignment.external_tool_tag, :context_url, tag_type)
|
|
end
|
|
end
|
|
|
|
if @assignment.submission_types.include?("online_upload") || @assignment.submission_types.include?("online_url")
|
|
@external_tools = ContextExternalTool.all_tools_for(@context, :user => @current_user, :placements => :homework_submission)
|
|
else
|
|
@external_tools = []
|
|
end
|
|
|
|
js_env({
|
|
:ROOT_OUTCOME_GROUP => outcome_group_json(@context.root_outcome_group, @current_user, session),
|
|
:COURSE_ID => @context.id,
|
|
:ASSIGNMENT_ID => @assignment.id,
|
|
:EXTERNAL_TOOLS => external_tools_json(@external_tools, @context, @current_user, session)
|
|
})
|
|
set_master_course_js_env_data(@assignment, @context)
|
|
conditional_release_js_env(@assignment, includes: :rule)
|
|
|
|
@can_view_grades = @context.grants_right?(@current_user, session, :view_all_grades)
|
|
@can_grade = @assignment.grants_right?(@current_user, session, :grade)
|
|
if @can_view_grades || @can_grade
|
|
visible_student_ids = @context.apply_enrollment_visibility(@context.all_student_enrollments, @current_user).pluck(:user_id)
|
|
@current_student_submissions = @assignment.submissions.where("submissions.submission_type IS NOT NULL").where(:user_id => visible_student_ids).to_a
|
|
end
|
|
|
|
# this will set @user_has_google_drive
|
|
user_has_google_drive
|
|
|
|
add_crumb(@assignment.title, polymorphic_url([@context, @assignment]))
|
|
|
|
@assignment_menu_tools = external_tools_display_hashes(:assignment_menu)
|
|
|
|
@mark_done = MarkDonePresenter.new(self, @context, params["module_item_id"], @current_user, @assignment)
|
|
|
|
@similarity_pledge = pledge_text
|
|
|
|
respond_to do |format|
|
|
format.html do
|
|
render locals: {
|
|
eula_url: @assignment.tool_settings_tool
|
|
&.try(:tool_proxy)
|
|
&.find_service(Assignment::Lti::EULA_SERVICE, 'GET')
|
|
&.endpoint
|
|
}
|
|
end
|
|
format.json { render :json => @assignment.as_json(:permissions => {:user => @current_user, :session => session}) }
|
|
end
|
|
end
|
|
end
|
|
|
|
def show_moderate
|
|
@assignment ||= @context.assignments.find(params[:assignment_id])
|
|
|
|
raise ActiveRecord::RecordNotFound unless @assignment.moderated_grading? && @assignment.published?
|
|
|
|
if authorized_action(@context, @current_user, :moderate_grades)
|
|
add_crumb(@assignment.title, polymorphic_url([@context, @assignment]))
|
|
add_crumb(t('Moderate'))
|
|
|
|
can_edit_grades = @context.grants_right?(@current_user, :manage_grades)
|
|
js_env({
|
|
ASSIGNMENT_TITLE: @assignment.title,
|
|
GRADES_PUBLISHED: @assignment.grades_published?,
|
|
COURSE_ID: @context.id,
|
|
STUDENT_CONTEXT_CARDS_ENABLED: @domain_root_account.feature_enabled?(:student_context_cards),
|
|
PERMISSIONS: {
|
|
view_grades: can_edit_grades || @context.grants_right?(@current_user, :view_all_grades),
|
|
edit_grades: can_edit_grades
|
|
},
|
|
URLS: {
|
|
student_submissions_url: polymorphic_url([:api_v1, @context, @assignment, :submissions]) + "?include[]=user_summary&include[]=provisional_grades",
|
|
publish_grades_url: api_v1_publish_provisional_grades_url({course_id: @context.id, assignment_id: @assignment.id}),
|
|
list_gradeable_students: api_v1_course_assignment_gradeable_students_url({course_id: @context.id, assignment_id: @assignment.id}) + "?include[]=provisional_grades&per_page=50",
|
|
add_moderated_students: api_v1_add_moderated_students_url({course_id: @context.id, assignment_id: @assignment.id}),
|
|
assignment_speedgrader_url: speed_grader_course_gradebook_url({course_id: @context.id, assignment_id: @assignment.id}),
|
|
provisional_grades_base_url: polymorphic_url([:api_v1, @context, @assignment]) + "/provisional_grades"
|
|
}})
|
|
|
|
respond_to do |format|
|
|
format.html { render }
|
|
end
|
|
end
|
|
end
|
|
|
|
def list_google_docs
|
|
assignment ||= @context.assignments.find(params[:id])
|
|
# prevent masquerading users from accessing google docs
|
|
if assignment.allow_google_docs_submission? && @real_current_user.blank?
|
|
docs = {}
|
|
begin
|
|
docs = google_drive_connection.list_with_extension_filter(assignment.allowed_extensions)
|
|
rescue GoogleDrive::NoTokenError => e
|
|
Canvas::Errors.capture_exception(:oauth, e)
|
|
rescue Google::APIClient::AuthorizationError => e
|
|
Canvas::Errors.capture_exception(:oauth, e)
|
|
rescue ArgumentError => e
|
|
Canvas::Errors.capture_exception(:oauth, e)
|
|
rescue => e
|
|
Canvas::Errors.capture_exception(:oauth, e)
|
|
raise e
|
|
end
|
|
respond_to do |format|
|
|
format.json { render json: docs.to_hash }
|
|
end
|
|
else
|
|
error_object = {errors:
|
|
{base: t('errors.google_docs_masquerade_rejected', "Unable to connect to Google Docs as a masqueraded user.")}
|
|
}
|
|
respond_to do |format|
|
|
format.json { render json: error_object, status: :bad_request }
|
|
end
|
|
end
|
|
end
|
|
|
|
def rubric
|
|
@assignment = @context.assignments.active.find(params[:assignment_id])
|
|
@root_outcome_group = outcome_group_json(@context.root_outcome_group, @current_user, session).to_json
|
|
if authorized_action(@assignment, @current_user, :read)
|
|
render :partial => 'shared/assignment_rubric_dialog'
|
|
end
|
|
end
|
|
|
|
def assign_peer_reviews
|
|
@assignment = @context.assignments.active.find(params[:assignment_id])
|
|
if authorized_action(@assignment, @current_user, :grade)
|
|
cnt = params[:peer_review_count].to_i
|
|
@assignment.peer_review_count = cnt if cnt > 0
|
|
@assignment.intra_group_peer_reviews = params[:intra_group_peer_reviews].present?
|
|
@assignment.assign_peer_reviews
|
|
respond_to do |format|
|
|
format.html { redirect_to named_context_url(@context, :context_assignment_peer_reviews_url, @assignment.id) }
|
|
end
|
|
end
|
|
end
|
|
|
|
def assign_peer_review
|
|
@assignment = @context.assignments.active.find(params[:assignment_id])
|
|
@student = @context.students_visible_to(@current_user).find params[:reviewer_id]
|
|
@reviewee = @context.students_visible_to(@current_user).find params[:reviewee_id]
|
|
if authorized_action(@assignment, @current_user, :grade)
|
|
@request = @assignment.assign_peer_review(@student, @reviewee)
|
|
respond_to do |format|
|
|
format.html { redirect_to named_context_url(@context, :context_assignment_peer_reviews_url, @assignment.id) }
|
|
format.json { render :json => @request.as_json(:methods => :asset_user_name) }
|
|
end
|
|
end
|
|
end
|
|
|
|
def remind_peer_review
|
|
@assignment = @context.assignments.active.find(params[:assignment_id])
|
|
if authorized_action(@assignment, @current_user, :grade)
|
|
@request = AssessmentRequest.where(id: params[:id]).first if params[:id].present?
|
|
respond_to do |format|
|
|
if @request.asset.assignment == @assignment && @request.send_reminder!
|
|
format.html { redirect_to named_context_url(@context, :context_assignment_peer_reviews_url) }
|
|
format.json { render :json => @request }
|
|
else
|
|
format.html { redirect_to named_context_url(@context, :context_assignment_peer_reviews_url) }
|
|
format.json { render :json => {:errors => {:base => t('errors.reminder_failed', "Reminder failed")}}, :status => :bad_request }
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def delete_peer_review
|
|
@assignment = @context.assignments.active.find(params[:assignment_id])
|
|
if authorized_action(@assignment, @current_user, :grade)
|
|
@request = AssessmentRequest.where(id: params[:id]).first if params[:id].present?
|
|
respond_to do |format|
|
|
if @request.asset.assignment == @assignment && @request.destroy
|
|
format.html { redirect_to named_context_url(@context, :context_assignment_peer_reviews_url) }
|
|
format.json { render :json => @request }
|
|
else
|
|
format.html { redirect_to named_context_url(@context, :context_assignment_peer_reviews_url) }
|
|
format.json { render :json => {:errors => {:base => t('errors.delete_reminder_failed', "Delete failed")}}, :status => :bad_request }
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def peer_reviews
|
|
@assignment = @context.assignments.active.find(params[:assignment_id])
|
|
if authorized_action(@assignment, @current_user, :grade)
|
|
if !@assignment.has_peer_reviews?
|
|
redirect_to named_context_url(@context, :context_assignment_url, @assignment.id)
|
|
return
|
|
end
|
|
|
|
student_scope = if @assignment.differentiated_assignments_applies?
|
|
@context.students_visible_to(@current_user).able_to_see_assignment_in_course_with_da(@assignment.id, @context.id)
|
|
else
|
|
@context.students_visible_to(@current_user)
|
|
end
|
|
|
|
@students = student_scope.not_fake_student.distinct.order_by_sortable_name
|
|
@submissions = @assignment.submissions.include_assessment_requests
|
|
end
|
|
end
|
|
|
|
def syllabus
|
|
rce_js_env(:sidebar)
|
|
add_crumb t '#crumbs.syllabus', "Syllabus"
|
|
active_tab = "Syllabus"
|
|
if authorized_action(@context, @current_user, [:read, :read_syllabus])
|
|
return unless tab_enabled?(@context.class::TAB_SYLLABUS)
|
|
@groups = @context.assignment_groups.active.order(
|
|
:position,
|
|
AssignmentGroup.best_unicode_collation_key('name')
|
|
).to_a
|
|
@syllabus_body = syllabus_user_content
|
|
|
|
hash = { :CONTEXT_ACTION_SOURCE => :syllabus }
|
|
append_sis_data(hash)
|
|
js_env(hash)
|
|
set_tutorial_js_env
|
|
|
|
log_asset_access([ "syllabus", @context ], "syllabus", 'other')
|
|
respond_to do |format|
|
|
format.html
|
|
end
|
|
end
|
|
end
|
|
|
|
def toggle_mute
|
|
return nil unless authorized_action(@context, @current_user, [:manage_grades, :view_all_grades])
|
|
@assignment = @context.assignments.active.find(params[:assignment_id])
|
|
method = if params[:status] == "true" then :mute! else :unmute! end
|
|
|
|
respond_to do |format|
|
|
if @assignment && @assignment.send(method)
|
|
format.json { render :json => @assignment }
|
|
else
|
|
format.json { render :json => @assignment, :status => :bad_request }
|
|
end
|
|
end
|
|
end
|
|
|
|
def create
|
|
defaults = {}
|
|
if params[:assignment] && params[:assignment][:post_to_sis].nil?
|
|
defaults[:post_to_sis] = @context.account.sis_default_grade_export[:value]
|
|
end
|
|
defaults[:time_zone_edited] = Time.zone.name if params[:assignment]
|
|
group = get_assignment_group(params[:assignment])
|
|
@assignment ||= @context.assignments.build(strong_assignment_params.merge(defaults))
|
|
|
|
if params[:assignment][:secure_params]
|
|
secure_params = Canvas::Security.decode_jwt params[:assignment][:secure_params]
|
|
@assignment.lti_context_id = secure_params[:lti_context_id]
|
|
end
|
|
|
|
@assignment.quiz_lti! if params.key?(:quiz_lti)
|
|
|
|
@assignment.workflow_state ||= "unpublished"
|
|
@assignment.updating_user = @current_user
|
|
@assignment.content_being_saved_by(@current_user)
|
|
@assignment.assignment_group = group if group
|
|
# if no due_at was given, set it to 11:59 pm in the creator's time zone
|
|
@assignment.infer_times
|
|
if authorized_action(@assignment, @current_user, :create)
|
|
respond_to do |format|
|
|
if @assignment.save
|
|
flash[:notice] = t 'notices.created', "Assignment was successfully created."
|
|
format.html { redirect_to named_context_url(@context, :context_assignment_url, @assignment.id) }
|
|
format.json { render :json => @assignment.as_json(:permissions => {:user => @current_user, :session => session}), :status => :created}
|
|
else
|
|
format.html { render :new }
|
|
format.json { render :json => @assignment.errors, :status => :bad_request }
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def new
|
|
@assignment ||= @context.assignments.temp_record
|
|
@assignment.workflow_state = 'unpublished'
|
|
add_crumb t "Create new"
|
|
|
|
if params[:submission_types] == 'online_quiz'
|
|
redirect_to new_course_quiz_url(@context, index_edit_params)
|
|
elsif params[:submission_types] == 'discussion_topic'
|
|
redirect_to new_polymorphic_url([@context, :discussion_topic], index_edit_params)
|
|
elsif @context.feature_enabled?(:conditional_release) && params[:submission_types] == 'wiki_page'
|
|
redirect_to new_polymorphic_url([@context, :wiki_page], index_edit_params)
|
|
else
|
|
@assignment.quiz_lti! if params.key?(:quiz_lti)
|
|
edit
|
|
end
|
|
end
|
|
|
|
def edit
|
|
rce_js_env(:highrisk)
|
|
@assignment ||= @context.assignments.active.find(params[:id])
|
|
if authorized_action(@assignment, @current_user, @assignment.new_record? ? :create : :update)
|
|
@assignment.title = params[:title] if params[:title]
|
|
@assignment.due_at = params[:due_at] if params[:due_at]
|
|
@assignment.points_possible = params[:points_possible] if params[:points_possible]
|
|
@assignment.submission_types = params[:submission_types] if params[:submission_types]
|
|
@assignment.assignment_group_id = params[:assignment_group_id] if params[:assignment_group_id]
|
|
@assignment.ensure_assignment_group(false)
|
|
|
|
if params.key?(:post_to_sis)
|
|
@assignment.post_to_sis = value_to_boolean(params[:post_to_sis])
|
|
elsif @assignment.new_record?
|
|
@assignment.post_to_sis = @context.account.sis_default_grade_export[:value]
|
|
end
|
|
|
|
if @assignment.submission_types == 'online_quiz' && @assignment.quiz
|
|
return redirect_to edit_course_quiz_url(@context, @assignment.quiz, index_edit_params)
|
|
elsif @assignment.submission_types == 'discussion_topic' && @assignment.discussion_topic
|
|
return redirect_to edit_polymorphic_url([@context, @assignment.discussion_topic], index_edit_params)
|
|
elsif @context.feature_enabled?(:conditional_release) &&
|
|
@assignment.submission_types == 'wiki_page' && @assignment.wiki_page
|
|
return redirect_to edit_polymorphic_url([@context, @assignment.wiki_page], index_edit_params)
|
|
end
|
|
|
|
assignment_groups = @context.assignment_groups.active
|
|
group_categories = @context.group_categories.
|
|
select { |c| !c.student_organized? }.
|
|
map { |c| { :id => c.id, :name => c.name } }
|
|
|
|
# if assignment has student submissions and is attached to a deleted group category,
|
|
# add that category to the ENV list so it can be shown on the edit page.
|
|
if @assignment.group_category_deleted_with_submissions?
|
|
locked_category = @assignment.group_category
|
|
group_categories << { :id => locked_category.id, :name => locked_category.name }
|
|
end
|
|
|
|
json_for_assignment_groups = assignment_groups.map do |group|
|
|
assignment_group_json(group, @current_user, session, [], {stringify_json_ids: true})
|
|
end
|
|
|
|
post_to_sis = Assignment.sis_grade_export_enabled?(@context)
|
|
hash = {
|
|
ASSIGNMENT_GROUPS: json_for_assignment_groups,
|
|
ASSIGNMENT_INDEX_URL: polymorphic_url([@context, :assignments]),
|
|
ASSIGNMENT_OVERRIDES: assignment_overrides_json(
|
|
@assignment.overrides_for(@current_user, ensure_set_not_empty: true),
|
|
@current_user
|
|
),
|
|
COURSE_ID: @context.id,
|
|
GROUP_CATEGORIES: group_categories,
|
|
HAS_GRADED_SUBMISSIONS: @assignment.graded_submissions_exist?,
|
|
KALTURA_ENABLED: !!feature_enabled?(:kaltura),
|
|
HAS_GRADING_PERIODS: @context.grading_periods?,
|
|
PLAGIARISM_DETECTION_PLATFORM: Lti::ToolProxy.capability_enabled_in_context?(
|
|
@assignment.course,
|
|
Lti::ResourcePlacement::SIMILARITY_DETECTION_LTI2
|
|
),
|
|
POST_TO_SIS: post_to_sis,
|
|
SIS_NAME: AssignmentUtil.post_to_sis_friendly_name(@context),
|
|
SECTION_LIST: @context.course_sections.active.map do |section|
|
|
{
|
|
id: section.id,
|
|
name: section.name,
|
|
start_at: section.start_at,
|
|
end_at: section.end_at,
|
|
override_course_and_term_dates: section.restrict_enrollments_to_section_dates
|
|
}
|
|
end,
|
|
VALID_DATE_RANGE: CourseDateRange.new(@context),
|
|
ANONYMOUS_INSTRUCTOR_ANNOTATIONS_ENABLED: ENV['ANONYMOUS_INSTRUCTOR_ANNOTATIONS'] == 'true'
|
|
}
|
|
|
|
add_crumb(@assignment.title, polymorphic_url([@context, @assignment]))
|
|
hash[:POST_TO_SIS_DEFAULT] = @context.account.sis_default_grade_export[:value] if post_to_sis && @assignment.new_record?
|
|
hash[:ASSIGNMENT] = assignment_json(@assignment, @current_user, session, override_dates: false)
|
|
hash[:ASSIGNMENT][:has_submitted_submissions] = @assignment.has_submitted_submissions?
|
|
hash[:URL_ROOT] = polymorphic_url([:api_v1, @context, :assignments])
|
|
hash[:CANCEL_TO] = @assignment.new_record? ? polymorphic_url([@context, :assignments]) : polymorphic_url([@context, @assignment])
|
|
hash[:CONTEXT_ID] = @context.id
|
|
hash[:CONTEXT_ACTION_SOURCE] = :assignments
|
|
hash[:DUE_DATE_REQUIRED_FOR_ACCOUNT] = AssignmentUtil.due_date_required_for_account?(@context)
|
|
hash[:MAX_NAME_LENGTH_REQUIRED_FOR_ACCOUNT] = AssignmentUtil.name_length_required_for_account?(@context)
|
|
hash[:MAX_NAME_LENGTH] = self.try(:context).try(:account).try(:sis_assignment_name_length_input).try(:[], :value).to_i
|
|
|
|
selected_tool = @assignment.tool_settings_tool
|
|
hash[:SELECTED_CONFIG_TOOL_ID] = selected_tool ? selected_tool.id : nil
|
|
hash[:SELECTED_CONFIG_TOOL_TYPE] = selected_tool ? selected_tool.class.to_s : nil
|
|
hash[:REPORT_VISIBILITY_SETTING] = @assignment.turnitin_settings[:originality_report_visibility]
|
|
|
|
if @context.grading_periods?
|
|
hash[:active_grading_periods] = GradingPeriod.json_for(@context, @current_user)
|
|
end
|
|
append_sis_data(hash)
|
|
if context.is_a?(Course)
|
|
hash[:allow_self_signup] = true # for group creation
|
|
hash[:group_user_type] = 'student'
|
|
end
|
|
js_env(hash)
|
|
conditional_release_js_env(@assignment)
|
|
set_master_course_js_env_data(@assignment, @context)
|
|
render :edit
|
|
end
|
|
end
|
|
|
|
# @API Delete an assignment
|
|
#
|
|
# Delete the given assignment.
|
|
#
|
|
# @example_request
|
|
# curl https://<canvas>/api/v1/courses/<course_id>/assignments/<assignment_id> \
|
|
# -X DELETE \
|
|
# -H 'Authorization: Bearer <token>'
|
|
# @returns Assignment
|
|
def destroy
|
|
@assignment = @context.assignments.active.api_id(params[:id])
|
|
if authorized_action(@assignment, @current_user, :delete)
|
|
return render_unauthorized_action if editing_restricted?(@assignment)
|
|
@assignment.destroy
|
|
|
|
respond_to do |format|
|
|
format.html { redirect_to(named_context_url(@context, :context_assignments_url)) }
|
|
format.json { render :json => assignment_json(@assignment, @current_user, session) }
|
|
end
|
|
end
|
|
end
|
|
|
|
protected
|
|
|
|
def strong_assignment_params
|
|
params.require(:assignment).
|
|
permit(:title, :name, :description, :due_at, :points_possible,
|
|
:grading_type, :submission_types, :assignment_group, :unlock_at, :lock_at,
|
|
:group_category, :group_category_id, :peer_review_count, :anonymous_peer_reviews,
|
|
:peer_reviews_due_at, :peer_reviews_assign_at, :grading_standard_id,
|
|
:peer_reviews, :automatic_peer_reviews, :grade_group_students_individually,
|
|
:notify_of_update, :time_zone_edited, :turnitin_enabled, :vericite_enabled,
|
|
:context, :position, :external_tool_tag_attributes, :freeze_on_copy,
|
|
:only_visible_to_overrides, :post_to_sis, :integration_id, :moderated_grading,
|
|
:omit_from_final_grade, :intra_group_peer_reviews,
|
|
:allowed_extensions => strong_anything,
|
|
:turnitin_settings => strong_anything,
|
|
:integration_data => strong_anything)
|
|
end
|
|
|
|
def get_assignment_group(assignment_params)
|
|
return unless assignment_params
|
|
if (group_id = assignment_params[:assignment_group_id]).present?
|
|
@context.assignment_groups.find(group_id)
|
|
end
|
|
end
|
|
|
|
def normalize_title_param
|
|
params[:title] ||= params[:name]
|
|
end
|
|
|
|
def index_edit_params
|
|
params.permit(:title, :due_at, :points_possible, :assignment_group_id, :return_to)
|
|
end
|
|
|
|
def pledge_text
|
|
(@assignment.turnitin_enabled? && @context.turnitin_pledge) ||
|
|
(@assignment.vericite_enabled? && @context.vericite_pledge) ||
|
|
@assignment.course.account.closest_turnitin_pledge
|
|
end
|
|
end
|