add the anonymous_instructor_annotations attribute to assignment

closes GRADE-157

this is currently hidden behind an environment variable until DocViewer
starts consuming this attribute and decides to expose it via a feature
flag

test plan:
* Setup the environment variable ANONYMOUS_INSTRUCTOR_ANNOTATIONS to
  'true'
* Start Canvas
* Go to create an assignment and verify that it contains a checkbox to
  anonymize instructor annotations for the new assignment
* Verify this checkbox works
* Edit the newly created assignment and verify the checkbox labelled
  anonymize instructor annotations always accurately reflects the choice
  made when saving the assignment

* Remove the ANONYMOUS_INSTRUCTOR_ANNOTATIONS environment variable
* Restart Canvas
* Go to create an assignment and verify it no longer contains a checkbox
  to anonymize instructor annotations
* Edit the assignment you created earlier and verify it also no longer
  contains a checkbox to anonymize instructor annotations

Change-Id: Ia43dee5c45ccd151319380e673d70dc509512ca8
Reviewed-on: https://gerrit.instructure.com/123646
Tested-by: Jenkins
Reviewed-by: Derek Bender <djbender@instructure.com>
Reviewed-by: Keith T. Garner <kgarner@instructure.com>
QA-Review: Indira Pai <ipai@instructure.com>
Product-Review: Matt Goodwin <mattg@instructure.com>
This commit is contained in:
Shahbaz Javeed 2017-08-22 23:46:14 -04:00
parent 0e4b88cebd
commit 140f5ec425
12 changed files with 155 additions and 7 deletions

View File

@ -200,6 +200,10 @@ define [
return @get 'moderated_grading' unless arguments.length > 0
@set 'moderated_grading', moderatedGradingBoolean
anonymousInstructorAnnotations: (anonymousInstructorAnnotationsBoolean) =>
return @get 'anonymous_instructor_annotations' unless arguments.length > 0
@set 'anonymous_instructor_annotations', anonymousInstructorAnnotationsBoolean
peerReviews: (peerReviewBoolean) =>
return @get 'peer_reviews' unless arguments.length > 0
@set 'peer_reviews', peerReviewBoolean
@ -414,7 +418,8 @@ define [
'allDates', 'hasDueDate', 'hasPointsPossible', 'singleSectionDueDate',
'moderatedGrading', 'postToSISEnabled', 'isOnlyVisibleToOverrides',
'omitFromFinalGrade', 'is_quiz_assignment', 'isQuizLTIAssignment',
'secureParams', 'inClosedGradingPeriod', 'dueDateRequired', 'submissionTypesFrozen'
'secureParams', 'inClosedGradingPeriod', 'dueDateRequired', 'submissionTypesFrozen',
'anonymousInstructorAnnotations'
]
hash =

View File

@ -337,6 +337,7 @@ define [
isLargeRoster: ENV?.IS_LARGE_ROSTER or false
conditionalReleaseServiceEnabled: ENV?.CONDITIONAL_RELEASE_SERVICE_ENABLED or false
lockedItems: @lockedItems
anonymousInstructorAnnotationsEnabled: ENV?.ANONYMOUS_INSTRUCTOR_ANNOTATIONS_ENABLED or false
_attachEditorToDescription: =>

View File

@ -478,7 +478,8 @@ class AssignmentsController < ApplicationController
override_course_and_term_dates: section.restrict_enrollments_to_section_dates
}
end,
VALID_DATE_RANGE: CourseDateRange.new(@context)
VALID_DATE_RANGE: CourseDateRange.new(@context),
ANONYMOUS_INSTRUCTOR_ANNOTATIONS_ENABLED: ENV['ANONYMOUS_INSTRUCTOR_ANNOTATIONS'] == 'true'
}
add_crumb(@assignment.title, polymorphic_url([@context, @assignment]))

View File

@ -291,7 +291,8 @@ class Assignment < ActiveRecord::Base
grades_published_at
omit_from_final_grade
grading_standard_id
)
anonymous_instructor_annotations
).freeze
def external_tool?
self.submission_types == 'external_tool'

View File

@ -50,7 +50,7 @@
/* for labels */
div.form-column-left {
min-width: 145px;
width: 145px;
text-align: right;
margin-top: 20px;
display: inline-block;

View File

@ -174,6 +174,18 @@
</fieldset>
{{/unless}}
{{#if anonymousInstructorAnnotationsEnabled}}
<fieldset>
<div class="form-column-left">{{#t}}Anonymous Instructor Annotations{{/t}}</div>
<div class="form-column-right" style="margin-top: 14px;">
<label class="checkbox">
{{checkbox "anonymousInstructorAnnotations" id="assignment_anonymous_instructor_annotations" name="anonymous_instructor_annotations"}}
{{#t}}Anonymize all annotations made by instructors on submissions for this assignment in SpeedGrader{{/t}}
</label>
</div>
</fieldset>
{{/if}}
</div>
{{#if canFreeze}}

View File

@ -0,0 +1,31 @@
#
# Copyright (C) 2017 - 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/>.
#
class AddAnonymousInstructorAnnotationsToAssignment < ActiveRecord::Migration[5.0]
tag :predeploy
def up
add_column :assignments, :anonymous_instructor_annotations, :boolean
change_column_default :assignments, :anonymous_instructor_annotations, false
end
def down
remove_column :assignments, :anonymous_instructor_annotations
end
end

View File

@ -0,0 +1,25 @@
#
# Copyright (C) 2017 - 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/>.
#
class BackfillAssignmentAnonymousInstructorAnnotations < ActiveRecord::Migration[5.0]
tag :postdeploy
def up
DataFixup::BackfillNulls.run(Assignment, :anonymous_instructor_annotations, default_value: false)
end
end

View File

@ -48,6 +48,7 @@ module Api::V1::Assignment
grading_standard_id
moderated_grading
omit_from_final_grade
anonymous_instructor_annotations
)
}.freeze
@ -389,7 +390,8 @@ module Api::V1::Assignment
notify_of_update
integration_id
omit_from_final_grade
)
anonymous_instructor_annotations
).freeze
API_ALLOWED_TURNITIN_SETTINGS = %w(
originality_report_visibility
@ -401,14 +403,14 @@ module Api::V1::Assignment
exclude_small_matches_type
exclude_small_matches_value
submit_papers_to
)
).freeze
API_ALLOWED_VERICITE_SETTINGS = %w(
originality_report_visibility
exclude_quoted
exclude_self_plag
store_in_index
)
).freeze
def create_api_assignment(assignment, assignment_params, user, context = assignment.context)
return :forbidden unless grading_periods_allow_submittable_create?(assignment, assignment_params)

View File

@ -783,6 +783,16 @@ define [
json = assignment.toView()
ok json.omitFromFinalGrade
test "returns true when anonymousInstructorAnnotations is true", ->
assignment = new Assignment(name: 'foo')
assignment.anonymousInstructorAnnotations(true);
strictEqual(assignment.toView().anonymousInstructorAnnotations, true)
test "returns false when anonymousInstructorAnnotations is false", ->
assignment = new Assignment(name: 'foo')
assignment.anonymousInstructorAnnotations(false);
strictEqual(assignment.toView().anonymousInstructorAnnotations, false)
QUnit.module "Assignment#isQuizLTIAssignment"
test "returns true if record uses quizzes 2", ->

View File

@ -744,3 +744,33 @@ define [
test 'does not show the load in new tab checkbox', ->
equal @view.$externalToolsNewTab.length, 0
QUnit.module 'EditView: Anonymous Instructor Annotations',
setup: ->
fakeENV.setup()
ENV.COURSE_ID = 1
@server = sinon.fakeServer.create()
teardown: ->
@server.restore()
fakeENV.teardown()
editView: ->
editView.apply(this, arguments)
test 'when environment is not set, does not enable editing the property', ->
view = @editView()
strictEqual(view.toJSON().anonymousInstructorAnnotationsEnabled, false)
strictEqual(view.$el.find('input#assignment_anonymous_instructor_annotations').length, 0)
test 'when environment is set to false, does not enable editing the property', ->
ENV.ANONYMOUS_INSTRUCTOR_ANNOTATIONS_ENABLED = false
view = @editView()
strictEqual(view.toJSON().anonymousInstructorAnnotationsEnabled, false)
strictEqual(view.$el.find('input#assignment_anonymous_instructor_annotations').length, 0)
test 'when environment is set to true, enables editing the property', ->
ENV.ANONYMOUS_INSTRUCTOR_ANNOTATIONS_ENABLED = true
view = @editView()
strictEqual(view.toJSON().anonymousInstructorAnnotationsEnabled, true)
strictEqual(view.$el.find('input#assignment_anonymous_instructor_annotations').length, 1)

View File

@ -661,6 +661,36 @@ describe AssignmentsController do
expect(assigns[:js_env][:SIS_NAME]).to eq('Foo Bar')
end
describe 'js_env ANONYMOUS_INSTRUCTOR_ANNOTATIONS_ENABLED' do
before(:each) do
user_session(@teacher)
end
after(:each) do
ENV.delete('ANONYMOUS_INSTRUCTOR_ANNOTATIONS')
end
it 'is true when the ANONYMOUS_INSTRUCTOR_ANNOTATIONS environment variable is set to true' do
ENV['ANONYMOUS_INSTRUCTOR_ANNOTATIONS'] = 'true'
get 'edit', params: { course_id: @course.id, id: @assignment.id }
expect(assigns[:js_env][:ANONYMOUS_INSTRUCTOR_ANNOTATIONS_ENABLED]).to be true
end
it 'is false when the ANONYMOUS_INSTRUCTOR_ANNOTATIONS environment variable is set to false' do
ENV['ANONYMOUS_INSTRUCTOR_ANNOTATIONS'] = 'false'
get 'edit', params: { course_id: @course.id, id: @assignment.id }
expect(assigns[:js_env][:ANONYMOUS_INSTRUCTOR_ANNOTATIONS_ENABLED]).to be false
end
it 'is false when the ANONYMOUS_INSTRUCTOR_ANNOTATIONS environment variable is not set' do
get 'edit', params: { course_id: @course.id, id: @assignment.id }
expect(assigns[:js_env][:ANONYMOUS_INSTRUCTOR_ANNOTATIONS_ENABLED]).to be false
end
end
it "bootstraps the correct message_handler id for LTI 2 tools to js_env" do
user_session(@teacher)
account = @course.account