add View Ungraded as 0 view option to Gradebook
closes EVAL-622 Test Plan - Enable the Feature Flag as a site admin. - Verify that the Gradebook View menu includes "View Ungraded as 0". - Select "View Ungraded as 0". Verify that this selection persists across page reloads of Gradebook. - De-select "View Ungraded as 0". Verify that this selection persists across page reloads of Gradebook. - Disable the Feature Flag as a site admin. Verify that the Gradebook View menu no longer includes "View Ungraded as 0". Change-Id: I49792de1408a428955f42f272604a87b42d6d8d9 Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/248205 Reviewed-by: Adrian Packel <apackel@instructure.com> Reviewed-by: Kai Bjorkman <kbjorkman@instructure.com> Reviewed-by: Spencer Olson <solson@instructure.com> Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Product-Review: Syed Hussain <shussain@instructure.com> QA-Review: Gary Mei <gmei@instructure.com>
This commit is contained in:
parent
558dfc18c1
commit
1adcb0bc1e
|
@ -141,7 +141,8 @@ export default do ->
|
|||
|
||||
getCourseFeaturesFromOptions = (options) ->
|
||||
{
|
||||
finalGradeOverrideEnabled: options.final_grade_override_enabled
|
||||
finalGradeOverrideEnabled: options.final_grade_override_enabled,
|
||||
allowViewUngradedAsZero: !!options.allow_view_ungraded_as_zero
|
||||
}
|
||||
|
||||
## Gradebook Display Settings
|
||||
|
@ -196,6 +197,7 @@ export default do ->
|
|||
commentsLoaded: false
|
||||
commentsUpdating: false
|
||||
editedCommentId: null
|
||||
viewUngradedAsZero: settings.view_ungraded_as_zero == 'true'
|
||||
}
|
||||
|
||||
## Gradebook Application State
|
||||
|
@ -1362,6 +1364,9 @@ export default do ->
|
|||
onSelectShowUnpublishedAssignments: @toggleUnpublishedAssignments
|
||||
onSelectShowStatusesModal: =>
|
||||
@statusesModal.open()
|
||||
onSelectViewUngradedAsZero: @toggleViewUngradedAsZero
|
||||
viewUngradedAsZero: @gridDisplaySettings.viewUngradedAsZero
|
||||
allowViewUngradedAsZero: @courseFeatures.allowViewUngradedAsZero
|
||||
|
||||
renderViewOptionsMenu: =>
|
||||
mountPoint = document.querySelector("[data-component='ViewOptionsMenu']")
|
||||
|
@ -1848,6 +1853,7 @@ export default do ->
|
|||
studentColumnDisplayAs = @getSelectedPrimaryInfo(),
|
||||
studentColumnSecondaryInfo = @getSelectedSecondaryInfo(),
|
||||
sortRowsBy = @getSortRowsBySetting(),
|
||||
viewUngradedAsZero = @gridDisplaySettings.viewUngradedAsZero,
|
||||
colors = @getGridColors()
|
||||
} = {}, successFn, errorFn) =>
|
||||
selectedViewOptionsFilters.push('') unless selectedViewOptionsFilters.length > 0
|
||||
|
@ -1866,6 +1872,7 @@ export default do ->
|
|||
sort_rows_by_column_id: sortRowsBy.columnId
|
||||
sort_rows_by_setting_key: sortRowsBy.settingKey
|
||||
sort_rows_by_direction: sortRowsBy.direction
|
||||
view_ungraded_as_zero: viewUngradedAsZero
|
||||
colors: colors
|
||||
|
||||
$.ajaxJSON(@options.settings_update_url, 'PUT', data, successFn, errorFn)
|
||||
|
@ -2484,6 +2491,18 @@ export default do ->
|
|||
toggleableAction
|
||||
)
|
||||
|
||||
toggleViewUngradedAsZero: =>
|
||||
toggleableAction = =>
|
||||
@gridDisplaySettings.viewUngradedAsZero = !@gridDisplaySettings.viewUngradedAsZero
|
||||
@updateColumnsAndRenderViewOptionsMenu()
|
||||
toggleableAction()
|
||||
|
||||
@saveSettings(
|
||||
{ viewUngradedAsZero: @gridDisplaySettings.viewUngradedAsZero },
|
||||
() =>, # on success, do nothing since the render happened earlier
|
||||
toggleableAction
|
||||
)
|
||||
|
||||
setAssignmentsLoaded: (loaded) =>
|
||||
@contentLoadStates.assignmentsLoaded = loaded
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ class GradebookSettingsController < ApplicationController
|
|||
:sort_rows_by_column_id,
|
||||
:sort_rows_by_setting_key,
|
||||
:sort_rows_by_direction,
|
||||
:view_ungraded_as_zero,
|
||||
{ colors: [ :late, :missing, :resubmitted, :dropped, :excused ] }
|
||||
)
|
||||
gradebook_settings_params[:enter_grades_as] = params[:gradebook_settings][:enter_grades_as]
|
||||
|
|
|
@ -482,7 +482,8 @@ class GradebooksController < ApplicationController
|
|||
submissions_url: api_v1_course_student_submissions_url(@context, grouped: '1'),
|
||||
teacher_notes: teacher_notes && custom_gradebook_column_json(teacher_notes, @current_user, session),
|
||||
user_asset_string: @current_user&.asset_string,
|
||||
version: params.fetch(:version, nil)
|
||||
version: params.fetch(:version, nil),
|
||||
allow_view_ungraded_as_zero: Account.site_admin.feature_enabled?(:view_ungraded_as_zero)
|
||||
}
|
||||
|
||||
js_env({
|
||||
|
|
|
@ -65,7 +65,10 @@ class ViewOptionsMenu extends React.Component {
|
|||
}).isRequired,
|
||||
onSelectShowStatusesModal: func.isRequired,
|
||||
showUnpublishedAssignments: bool.isRequired,
|
||||
onSelectShowUnpublishedAssignments: func.isRequired
|
||||
onSelectShowUnpublishedAssignments: func.isRequired,
|
||||
onSelectViewUngradedAsZero: func.isRequired,
|
||||
viewUngradedAsZero: bool.isRequired,
|
||||
allowViewUngradedAsZero: bool.isRequired
|
||||
}
|
||||
|
||||
onFilterSelect = (_event, filters) => {
|
||||
|
@ -215,6 +218,17 @@ class ViewOptionsMenu extends React.Component {
|
|||
{I18n.t('Statuses…')}
|
||||
</Menu.Item>
|
||||
|
||||
{this.props.allowViewUngradedAsZero && (
|
||||
<Menu.Group label={I18n.t('View Options')}>
|
||||
<Menu.Item
|
||||
onSelect={this.props.onSelectViewUngradedAsZero}
|
||||
selected={this.props.viewUngradedAsZero}
|
||||
>
|
||||
{I18n.t('View Ungraded as 0')}
|
||||
</Menu.Item>
|
||||
</Menu.Group>
|
||||
)}
|
||||
|
||||
<Menu.Separator />
|
||||
|
||||
<Menu.Group allowMultiple label={I18n.t('Columns')}>
|
||||
|
|
|
@ -63,3 +63,9 @@ responsive_student_grades_page:
|
|||
applies_to: RootAccount
|
||||
display_name: Responsive Student Grades Page
|
||||
description: Makes the student grades page responsive.
|
||||
view_ungraded_as_zero:
|
||||
state: hidden
|
||||
applies_to: SiteAdmin
|
||||
display_name: View Ungraded as Zero View in Gradebook
|
||||
description: The Gradebook will factor in ungraded submissions as if they were given a score of zero for
|
||||
calculations. This is just a view for the teacher, and does not affect actual scoring.
|
||||
|
|
|
@ -50,6 +50,7 @@ RSpec.describe GradebookSettingsController, type: :controller do
|
|||
"sort_rows_by_column_id" => "student",
|
||||
"sort_rows_by_setting_key" => "sortable_name",
|
||||
"sort_rows_by_direction" => "descending",
|
||||
"view_ungraded_as_zero" => "true",
|
||||
"colors" => {
|
||||
"late" => "#000000",
|
||||
"missing" => "#000001",
|
||||
|
@ -96,8 +97,9 @@ RSpec.describe GradebookSettingsController, type: :controller do
|
|||
it { is_expected.to include 'sort_rows_by_column_id' => 'student' }
|
||||
it { is_expected.to include 'sort_rows_by_setting_key' => 'sortable_name' }
|
||||
it { is_expected.to include 'sort_rows_by_direction' => 'descending' }
|
||||
it { is_expected.to include 'view_ungraded_as_zero' => 'true' }
|
||||
it { is_expected.not_to include 'colors' }
|
||||
it { is_expected.to have(12).items } # ensure we add specs for new additions
|
||||
it { is_expected.to have(13).items } # ensure we add specs for new additions
|
||||
|
||||
context 'colors' do
|
||||
subject { json_parse.fetch('gradebook_settings').fetch('colors') }
|
||||
|
|
|
@ -843,6 +843,19 @@ describe GradebooksController do
|
|||
end
|
||||
end
|
||||
|
||||
describe "view ungraded as zero" do
|
||||
it "sets allow_view_ungraded_as_zero in the ENV to true if the feature is enabled" do
|
||||
Account.site_admin.enable_feature!(:view_ungraded_as_zero)
|
||||
get :show, params: { course_id: @course.id }
|
||||
expect(gradebook_options.fetch(:allow_view_ungraded_as_zero)).to be true
|
||||
end
|
||||
|
||||
it "sets allow_view_ungraded_as_zero in the ENV to false if the feature is not enabled" do
|
||||
get :show, params: { course_id: @course.id }
|
||||
expect(gradebook_options.fetch(:allow_view_ungraded_as_zero)).to be false
|
||||
end
|
||||
end
|
||||
|
||||
describe "dataloader_improvements" do
|
||||
# TODO: remove this entire block with TALLY-831
|
||||
|
||||
|
|
|
@ -2436,6 +2436,32 @@ QUnit.module('Gradebook#getViewOptionsMenuProps', () => {
|
|||
const {showUnpublishedAssignments} = createGradebook({settings}).getViewOptionsMenuProps()
|
||||
strictEqual(showUnpublishedAssignments, false)
|
||||
})
|
||||
|
||||
test('viewUngradedAsZero is true when settings.view_ungraded_as_zero is "true"', () => {
|
||||
const settings = {view_ungraded_as_zero: 'true'}
|
||||
const {viewUngradedAsZero} = createGradebook({settings}).getViewOptionsMenuProps()
|
||||
strictEqual(viewUngradedAsZero, true)
|
||||
})
|
||||
|
||||
test('viewUngradedAsZero is false when settings.view_ungraded_as_zero is "false"', () => {
|
||||
const settings = {view_ungraded_as_zero: 'false'}
|
||||
const {viewUngradedAsZero} = createGradebook({settings}).getViewOptionsMenuProps()
|
||||
strictEqual(viewUngradedAsZero, false)
|
||||
})
|
||||
|
||||
test('allowViewUngradedAsZero is true when allow_view_ungraded_as_zero is true', () => {
|
||||
const {allowViewUngradedAsZero} = createGradebook({
|
||||
allow_view_ungraded_as_zero: true
|
||||
}).getViewOptionsMenuProps()
|
||||
strictEqual(allowViewUngradedAsZero, true)
|
||||
})
|
||||
|
||||
test('allowViewUngradedAsZero is false when allow_view_ungraded_as_zero is false', () => {
|
||||
const {allowViewUngradedAsZero} = createGradebook({
|
||||
allow_view_ungraded_as_zero: false
|
||||
}).getViewOptionsMenuProps()
|
||||
strictEqual(allowViewUngradedAsZero, false)
|
||||
})
|
||||
})
|
||||
|
||||
QUnit.module('Gradebook#createTeacherNotes', {
|
||||
|
|
|
@ -45,7 +45,10 @@ function defaultProps({props, filterSettings} = {}) {
|
|||
},
|
||||
onSelectShowStatusesModal() {},
|
||||
onSelectShowUnpublishedAssignments() {},
|
||||
onSelectViewUngradedAsZero() {},
|
||||
showUnpublishedAssignments: false,
|
||||
viewUngradedAsZero: false,
|
||||
allowViewUngradedAsZero: false,
|
||||
finalGradeOverrideEnabled: false,
|
||||
teacherNotes: {
|
||||
disabled: false,
|
||||
|
@ -234,6 +237,74 @@ test('onSelect is called with list of selected filters upon any selection change
|
|||
strictEqual(onSelect.calledWithExactly(['assignmentGroups', 'sections', 'gradingPeriods']), true)
|
||||
})
|
||||
|
||||
QUnit.module('ViewOptionsMenu - view ungraded as 0', {
|
||||
mountViewOptionsMenu({
|
||||
viewUngradedAsZero = false,
|
||||
allowViewUngradedAsZero = false,
|
||||
onSelectViewUngradedAsZero = () => {}
|
||||
} = {}) {
|
||||
const props = defaultProps()
|
||||
return mount(
|
||||
<ViewOptionsMenu
|
||||
{...props}
|
||||
viewUngradedAsZero={viewUngradedAsZero}
|
||||
allowViewUngradedAsZero={allowViewUngradedAsZero}
|
||||
onSelectViewUngradedAsZero={onSelectViewUngradedAsZero}
|
||||
/>
|
||||
)
|
||||
},
|
||||
|
||||
teardown() {
|
||||
if (this.wrapper) {
|
||||
this.wrapper.unmount()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
test('"View Ungraded As 0" is shown when allowViewUngradedAsZero is true', function() {
|
||||
this.wrapper = this.mountViewOptionsMenu({allowViewUngradedAsZero: true})
|
||||
this.wrapper.find('button').simulate('click')
|
||||
ok(getMenuItem(this.wrapper.instance().menuContent, 'View Ungraded as 0'))
|
||||
})
|
||||
|
||||
test('"View Ungraded As 0" is not shown when allowViewUngradedAsZero is false', function() {
|
||||
this.wrapper = this.mountViewOptionsMenu({allowViewUngradedAsZero: false})
|
||||
this.wrapper.find('button').simulate('click')
|
||||
notOk(getMenuItem(this.wrapper.instance().menuContent, 'View Ungraded as 0'))
|
||||
})
|
||||
|
||||
test('"View Ungraded As 0" is selected when viewUngradedAsZero is true', function() {
|
||||
this.wrapper = this.mountViewOptionsMenu({
|
||||
viewUngradedAsZero: true,
|
||||
allowViewUngradedAsZero: true
|
||||
})
|
||||
this.wrapper.find('button').simulate('click')
|
||||
const menuItem = getMenuItem(this.wrapper.instance().menuContent, 'View Ungraded as 0')
|
||||
strictEqual(menuItem.getAttribute('aria-checked'), 'true')
|
||||
})
|
||||
|
||||
test('"View Ungraded As 0" is not selected when viewUngradedAsZero is false', function() {
|
||||
this.wrapper = this.mountViewOptionsMenu({
|
||||
viewUngradedAsZero: false,
|
||||
allowViewUngradedAsZero: true
|
||||
})
|
||||
this.wrapper.find('button').simulate('click')
|
||||
const menuItem = getMenuItem(this.wrapper.instance().menuContent, 'View Ungraded as 0')
|
||||
strictEqual(menuItem.getAttribute('aria-checked'), 'false')
|
||||
})
|
||||
|
||||
test('onSelectViewUngradedAsZero is called when selected', function() {
|
||||
const onSelectViewUngradedAsZeroStub = sinon.stub()
|
||||
this.wrapper = this.mountViewOptionsMenu({
|
||||
viewUngradedAsZero: false,
|
||||
allowViewUngradedAsZero: true,
|
||||
onSelectViewUngradedAsZero: onSelectViewUngradedAsZeroStub
|
||||
})
|
||||
this.wrapper.find('button').simulate('click')
|
||||
getMenuItem(this.wrapper.instance().menuContent, 'View Ungraded as 0').click()
|
||||
strictEqual(onSelectViewUngradedAsZeroStub.callCount, 1)
|
||||
})
|
||||
|
||||
QUnit.module('ViewOptionsMenu - unpublished assignments', {
|
||||
mountViewOptionsMenu({
|
||||
showUnpublishedAssignments = true,
|
||||
|
@ -345,7 +416,7 @@ test('Due Date - Oldest to Newest is selected when criterion is due_date and dir
|
|||
strictEqual(menuItem.getAttribute('aria-checked'), 'true')
|
||||
})
|
||||
|
||||
test('Due Date - Oldest to Newest is selected when criterion is due_date and direction is ascending', function() {
|
||||
test('Due Date - Newest to Oldest is selected when criterion is due_date and direction is descending', function() {
|
||||
const wrapper = mountAndOpenOptions(this.props('due_date', 'descending'))
|
||||
const menuItem = getMenuItem(
|
||||
wrapper.instance().menuContent,
|
||||
|
@ -365,7 +436,7 @@ test('Points - Lowest to Highest is selected when criterion is points and direct
|
|||
strictEqual(menuItem.getAttribute('aria-checked'), 'true')
|
||||
})
|
||||
|
||||
test('Points - Lowest to Highest is selected when criterion is points and direction is ascending', function() {
|
||||
test('Points - Highest to Lowest is selected when criterion is points and direction is descending', function() {
|
||||
const wrapper = mountAndOpenOptions(this.props('points', 'descending'))
|
||||
const menuItem = getMenuItem(
|
||||
wrapper.instance().menuContent,
|
||||
|
|
Loading…
Reference in New Issue