prettify new gradebook

refs GRADE-1934

test plan:
 * Verify Jenkins passes

Change-Id: I5d4d69e45955bb2beae61f5a3764e81c1e9d9def
Reviewed-on: https://gerrit.instructure.com/177584
Tested-by: Jenkins
Reviewed-by: Derek Bender <djbender@instructure.com>
QA-Review: Jeremy Neander <jneander@instructure.com>
Product-Review: Jeremy Neander <jneander@instructure.com>
This commit is contained in:
Jeremy Neander 2019-01-11 08:25:10 -06:00
parent 08e9fbcca2
commit f54e1ec1b9
47 changed files with 3808 additions and 3075 deletions

View File

@ -42,10 +42,10 @@ class GradebookRouter extends Backbone.Router {
initialize() {
this.isLoaded = false
this.views = {}
ENV.GRADEBOOK_OPTIONS.assignmentOrOutcome = getGradebookTab();
ENV.GRADEBOOK_OPTIONS.navigate = this.navigate.bind(this);
this.views.assignment = new Gradebook(this.gradebookOptions());
this.views.assignment.initialize();
ENV.GRADEBOOK_OPTIONS.assignmentOrOutcome = getGradebookTab()
ENV.GRADEBOOK_OPTIONS.navigate = this.navigate.bind(this)
this.views.assignment = new Gradebook(this.gradebookOptions())
this.views.assignment.initialize()
if (ENV.GRADEBOOK_OPTIONS.outcome_gradebook_enabled) {
this.views.outcome = this.initOutcomes()
this.renderPagination(0, 0)
@ -59,7 +59,7 @@ class GradebookRouter extends Backbone.Router {
...ENV.GRADEBOOK_OPTIONS,
locale: ENV.LOCALE,
currentUserId: ENV.current_user_id
};
}
}
initOutcomes() {
@ -74,8 +74,12 @@ class GradebookRouter extends Backbone.Router {
renderPagination(page, pageCount) {
ReactDOM.render(
<Paginator page={page} pageCount={pageCount} loadPage={(p) => this.views.outcome.loadPage(p)} />,
document.getElementById("outcome-gradebook-paginator")
<Paginator
page={page}
pageCount={pageCount}
loadPage={p => this.views.outcome.loadPage(p)}
/>,
document.getElementById('outcome-gradebook-paginator')
)
}
@ -98,7 +102,7 @@ class GradebookRouter extends Backbone.Router {
tab() {
let view = getGradebookTab()
window.tab = view
if ((view !== 'outcome') || !this.views.outcome) {
if (view !== 'outcome' || !this.views.outcome) {
view = 'assignment'
}
$('.assignment-gradebook-container, .outcome-gradebook-container > div').addClass('hidden')

View File

@ -21,70 +21,77 @@ import cheaterDepaginate from '../shared/CheatDepaginator'
import StudentContentDataLoader from './default_gradebook/DataLoader/StudentContentDataLoader'
function getStudentIds(courseId) {
const url = `/courses/${courseId}/gradebook/user_ids`;
return $.ajaxJSON(url, 'GET', {});
const url = `/courses/${courseId}/gradebook/user_ids`
return $.ajaxJSON(url, 'GET', {})
}
function getGradingPeriodAssignments(courseId) {
const url = `/courses/${courseId}/gradebook/grading_period_assignments`;
return $.ajaxJSON(url, 'GET', {});
const url = `/courses/${courseId}/gradebook/grading_period_assignments`
return $.ajaxJSON(url, 'GET', {})
}
function getAssignmentGroups(url, params) {
return cheaterDepaginate(url, params);
return cheaterDepaginate(url, params)
}
function getContextModules(url) {
return cheaterDepaginate(url);
return cheaterDepaginate(url)
}
function getCustomColumns(url) {
return cheaterDepaginate(url, { include_hidden: true });
return cheaterDepaginate(url, {include_hidden: true})
}
function getDataForColumn(columnId, url, params, cb) {
const columnUrl = url.replace(/:id/, columnId);
const augmentedCallback = data => cb(columnId, data);
return cheaterDepaginate(columnUrl, params, augmentedCallback);
const columnUrl = url.replace(/:id/, columnId)
const augmentedCallback = data => cb(columnId, data)
return cheaterDepaginate(columnUrl, params, augmentedCallback)
}
function getCustomColumnData(options, customColumnsDfd, waitForDfds) {
const url = options.customColumnDataURL;
const params = options.customColumnDataParams;
const cb = options.customColumnDataPageCb;
const customColumnDataLoaded = $.Deferred();
const url = options.customColumnDataURL
const params = options.customColumnDataParams
const cb = options.customColumnDataPageCb
const customColumnDataLoaded = $.Deferred()
if (url) {
// waitForDfds ensures that custom column data is loaded *last*
$.when(...waitForDfds).then(() => {
if (options.customColumnIds) {
const customColumnDataDfds = options.customColumnIds.map(columnId => getDataForColumn(columnId, url, params, cb));
$.when(...customColumnDataDfds).then(() => customColumnDataLoaded.resolve());
const customColumnDataDfds = options.customColumnIds.map(columnId =>
getDataForColumn(columnId, url, params, cb)
)
$.when(...customColumnDataDfds).then(() => customColumnDataLoaded.resolve())
} else {
customColumnsDfd.then((customColumns) => {
const customColumnDataDfds = customColumns.map(col => getDataForColumn(col.id, url, params, cb));
$.when(...customColumnDataDfds).then(() => customColumnDataLoaded.resolve());
});
customColumnsDfd.then(customColumns => {
const customColumnDataDfds = customColumns.map(col =>
getDataForColumn(col.id, url, params, cb)
)
$.when(...customColumnDataDfds).then(() => customColumnDataLoaded.resolve())
})
}
});
})
}
return customColumnDataLoaded;
return customColumnDataLoaded
}
function loadGradebookData(opts) {
const gotAssignmentGroups = getAssignmentGroups(opts.assignmentGroupsURL, opts.assignmentGroupsParams);
const gotAssignmentGroups = getAssignmentGroups(
opts.assignmentGroupsURL,
opts.assignmentGroupsParams
)
if (opts.onlyLoadAssignmentGroups) {
return { gotAssignmentGroups };
return {gotAssignmentGroups}
}
// Begin loading Students before any other data.
const gotStudentIds = getStudentIds(opts.courseId);
let gotGradingPeriodAssignments;
const gotStudentIds = getStudentIds(opts.courseId)
let gotGradingPeriodAssignments
if (opts.getGradingPeriodAssignments) {
gotGradingPeriodAssignments = getGradingPeriodAssignments(opts.courseId);
gotGradingPeriodAssignments = getGradingPeriodAssignments(opts.courseId)
}
const gotCustomColumns = getCustomColumns(opts.customColumnsURL);
const gotCustomColumns = getCustomColumns(opts.customColumnsURL)
const studentContentDataLoader = new StudentContentDataLoader({
courseId: opts.courseId,
@ -100,7 +107,7 @@ function loadGradebookData (opts) {
submissionsUrl: opts.submissionsURL
})
const gotContextModules = getContextModules(opts.contextModulesURL);
const gotContextModules = getContextModules(opts.contextModulesURL)
const gotStudents = $.Deferred()
const gotSubmissions = $.Deferred()
@ -112,7 +119,7 @@ function loadGradebookData (opts) {
})
// Custom Column Data will load only after custom columns and all submissions.
const gotCustomColumnData = getCustomColumnData(opts, gotCustomColumns, [gotSubmissions]);
const gotCustomColumnData = getCustomColumnData(opts, gotCustomColumns, [gotSubmissions])
return {
gotAssignmentGroups,
@ -123,10 +130,10 @@ function loadGradebookData (opts) {
gotStudents,
gotSubmissions,
gotCustomColumnData
};
}
}
export default {
getDataForColumn,
loadGradebookData
};
}

View File

@ -31,17 +31,17 @@ class PostGradesApp extends React.Component {
labelText: string.isRequired,
store: shape({
addChangeListener: func.isRequired,
removeChangeListener: func.isRequired,
removeChangeListener: func.isRequired
}).isRequired,
renderAsButton: bool,
returnFocusTo: shape({
focus: func.isRequired
}).isRequired
};
}
static defaultProps = {
renderAsButton: false
};
}
static AppLaunch(store, returnFocusTo) {
const $dialog = $('<div class="post-grades-dialog">').dialog({
@ -55,21 +55,21 @@ class PostGradesApp extends React.Component {
resizable: false,
buttons: [],
close() {
ReactDOM.unmountComponentAtNode(this);
$(this).remove();
ReactDOM.unmountComponentAtNode(this)
$(this).remove()
if (returnFocusTo) {
returnFocusTo.focus();
returnFocusTo.focus()
}
}
});
})
function closeDialog(e) {
e.preventDefault();
$dialog.dialog('close');
e.preventDefault()
$dialog.dialog('close')
}
store.reset()
ReactDOM.render(<PostGradesDialog store={store} closeDialog={closeDialog} />, $dialog[0]);
ReactDOM.render(<PostGradesDialog store={store} closeDialog={closeDialog} />, $dialog[0])
}
componentDidMount() {
@ -77,35 +77,32 @@ class PostGradesApp extends React.Component {
this.props.store.addChangeListener(this.boundForceUpdate)
}
componentWillUnmount () { this.props.store.removeChangeListener(this.boundForceUpdate) }
componentWillUnmount() {
this.props.store.removeChangeListener(this.boundForceUpdate)
}
openDialog(e) {
e.preventDefault();
e.preventDefault()
PostGradesApp.AppLaunch(this.props.store, this.props.returnFocusTo);
PostGradesApp.AppLaunch(this.props.store, this.props.returnFocusTo)
}
render() {
const navClass = classnames({
'ui-button': this.props.renderAsButton
});
})
if (this.props.renderAsButton) {
return (
<button
id="post-grades-button"
className={navClass}
onClick={this.openDialog}
>{this.props.labelText}</button>
);
<button id="post-grades-button" className={navClass} onClick={this.openDialog}>
{this.props.labelText}
</button>
)
} else {
return (
<a
tabIndex={0}
id="post-grades-button"
className={navClass}
onClick={this.openDialog}
>{this.props.labelText}</a>
);
<a tabIndex={0} id="post-grades-button" className={navClass} onClick={this.openDialog}>
{this.props.labelText}
</a>
)
}
}
}

View File

@ -135,7 +135,8 @@ class PostGradesDialogCorrectionsPage extends React.Component {
onClick={this.ignoreErrorsThenProceed}
>
{errorCount > 0 ? I18n.t('Ignore These') : I18n.t('Continue')}
&nbsp;<i className="icon-arrow-right" />
&nbsp;
<i className="icon-arrow-right" />
</button>
</div>
</form>

View File

@ -63,7 +63,8 @@ class PostGradesDialogNeedsGradingPage extends React.Component {
className="btn btn-primary"
onClick={this.props.leaveNeedsGradingPage}
>
{I18n.t('Continue')}&nbsp;<i className="icon-arrow-right" />
{I18n.t('Continue')}&nbsp;
<i className="icon-arrow-right" />
</button>
</div>
</form>

View File

@ -21,12 +21,11 @@ import _ from 'underscore'
import createStore from '../../shared/helpers/createStore'
import assignmentUtils from '../../gradezilla/SISGradePassback/assignmentUtils'
var PostGradesStore = (state) => {
var PostGradesStore = state => {
var store = $.extend(createStore(state), {
reset() {
var assignments = this.getAssignments()
_.each(assignments, (a) => a.please_ignore = false)
_.each(assignments, a => (a.please_ignore = false))
this.setState({
assignments: assignments,
pleaseShowNeedsGradingPage: false
@ -44,14 +43,12 @@ import assignmentUtils from '../../gradezilla/SISGradePassback/assignmentUtils'
getSISSectionId(section_id) {
var sections = this.getState().sections
return (sections && sections[section_id]) ?
sections[section_id].sis_section_id :
null;
return sections && sections[section_id] ? sections[section_id].sis_section_id : null
},
allOverrideIds(a) {
var overrides = []
_.each(a.overrides, (o) => {
_.each(a.overrides, o => {
overrides.push(o.course_section_id)
})
return overrides
@ -60,11 +57,13 @@ import assignmentUtils from '../../gradezilla/SISGradePassback/assignmentUtils'
overrideForEveryone(a) {
var overrides = this.allOverrideIds(a)
var sections = _.keys(this.getState().sections)
var section_ids_with_no_overrides = $(sections).not(overrides).get();
var section_ids_with_no_overrides = $(sections)
.not(overrides)
.get()
var section_for_everyone = _.find(section_ids_with_no_overrides, (o) => {
var section_for_everyone = _.find(section_ids_with_no_overrides, o => {
return state.selected.id == o
});
})
return section_for_everyone
},
@ -84,7 +83,7 @@ import assignmentUtils from '../../gradezilla/SISGradePassback/assignmentUtils'
}
// A second loop is needed to ensure non-unique name errors are included
// in hasError
_.each(assignments, (a) => {
_.each(assignments, a => {
a.original_error = assignmentUtils.hasError(assignments, a)
})
this.setState({assignments: assignments})
@ -96,13 +95,19 @@ import assignmentUtils from '../../gradezilla/SISGradePassback/assignmentUtils'
},
validCheck(a) {
if(a.overrideForThisSection != undefined && a.currentlySelected.type == 'course' && a.currentlySelected.id.toString() == a.overrideForThisSection.course_section_id){
if (
a.overrideForThisSection != undefined &&
a.currentlySelected.type == 'course' &&
a.currentlySelected.id.toString() == a.overrideForThisSection.course_section_id
) {
return a.due_at != null ? true : false
}
else if(a.overrideForThisSection != undefined && a.currentlySelected.type == 'section' && a.currentlySelected.id.toString() == a.overrideForThisSection.course_section_id){
} else if (
a.overrideForThisSection != undefined &&
a.currentlySelected.type == 'section' &&
a.currentlySelected.id.toString() == a.overrideForThisSection.course_section_id
) {
return a.overrideForThisSection.due_at != null ? true : false
}
else{
} else {
return true
}
},
@ -110,58 +115,62 @@ import assignmentUtils from '../../gradezilla/SISGradePassback/assignmentUtils'
getAssignments() {
var assignments = this.getState().assignments
var state = this.getState()
if (state.selected.type == "section") {
_.each(assignments, (a) => {
if (state.selected.type == 'section') {
_.each(assignments, a => {
a.recentlyUpdated = false
a.currentlySelected = state.selected
a.sectionCount = _.keys(state.sections).length
a.overrideForThisSection = _.find(a.overrides, (override) => {
return override.course_section_id == state.selected.id;
});
a.overrideForThisSection = _.find(a.overrides, override => {
return override.course_section_id == state.selected.id
})
//Handle assignment with overrides and the 'Everyone Else' scenario with a section that does not have any overrides
//cleanup overrideForThisSection logic
if(a.overrideForThisSection == undefined){ a.selectedSectionForEveryone = this.overrideForEveryone(a) }
});
if (a.overrideForThisSection == undefined) {
a.selectedSectionForEveryone = this.overrideForEveryone(a)
}
})
} else {
_.each(assignments, (a) => {
_.each(assignments, a => {
a.recentlyUpdated = false
a.currentlySelected = state.selected
a.sectionCount = _.keys(state.sections).length
//Course is currentlySlected with sections that have overrides AND are invalid
a.overrideForThisSection = _.find(a.overrides, (override) => {
return override.due_at == null || typeof(override.due_at) == 'object';
});
a.overrideForThisSection = _.find(a.overrides, override => {
return override.due_at == null || typeof override.due_at == 'object'
})
//Handle assignment with overrides and the 'Everyone Else' scenario with the course currentlySelected
if(a.overrideForThisSection == undefined){ a.selectedSectionForEveryone = this.overrideForEveryone(a) }
});
if (a.overrideForThisSection == undefined) {
a.selectedSectionForEveryone = this.overrideForEveryone(a)
}
return assignments;
})
}
return assignments
},
getAssignment(assignment_id) {
var assignments = this.getAssignments()
return _.find(assignments, (a) => a.id == assignment_id)
return _.find(assignments, a => a.id == assignment_id)
},
setSelectedSection(section) {
var state = this.getState()
var section_id = parseInt(section)
var selected;
var selected
if (section) {
selected = {
type: "section",
type: 'section',
id: section_id,
sis_id: this.getSISSectionId(section_id)
};
}
} else {
selected = {
type: "course",
type: 'course',
id: state.course.id,
sis_id: state.course.sis_id
};
}
}
this.setState({selected: selected, sectionToShow: section})
@ -169,16 +178,20 @@ import assignmentUtils from '../../gradezilla/SISGradePassback/assignmentUtils'
updateAssignment(assignment_id, newAttrs) {
var assignments = this.getAssignments()
var assignment = _.find(assignments, (a) => a.id == assignment_id)
var assignment = _.find(assignments, a => a.id == assignment_id)
$.extend(assignment, newAttrs)
this.setState({assignments: assignments})
},
updateAssignmentDate(assignment_id, date) {
var assignments = this.getState().assignments
var assignment = _.find(assignments, (a) => a.id == assignment_id)
var assignment = _.find(assignments, a => a.id == assignment_id)
//the assignment has an override and the override being updated is for the section that is currentlySelected update it
if(assignment.overrideForThisSection != undefined && assignment.currentlySelected.id.toString() == assignment.overrideForThisSection.course_section_id) {
if (
assignment.overrideForThisSection != undefined &&
assignment.currentlySelected.id.toString() ==
assignment.overrideForThisSection.course_section_id
) {
assignment.overrideForThisSection.due_at = date
assignment.please_ignore = false
assignment.hadOriginalErrors = true
@ -187,7 +200,11 @@ import assignmentUtils from '../../gradezilla/SISGradePassback/assignmentUtils'
}
//the section override being set from the course level of the sction dropdown
else if(assignment.overrideForThisSection != undefined && assignment.currentlySelected.id.toString() != assignment.overrideForThisSection.course_section_id){
else if (
assignment.overrideForThisSection != undefined &&
assignment.currentlySelected.id.toString() !=
assignment.overrideForThisSection.course_section_id
) {
assignment.overrideForThisSection.due_at = date
assignment.please_ignore = false
assignment.hadOriginalErrors = true
@ -197,7 +214,11 @@ import assignmentUtils from '../../gradezilla/SISGradePassback/assignmentUtils'
//update normal assignment and the 'Everyone Else' scenario if the course is currentlySelected
else {
this.updateAssignment(assignment_id, {due_at: date, please_ignore: false, hadOriginalErrors: true})
this.updateAssignment(assignment_id, {
due_at: date,
please_ignore: false,
hadOriginalErrors: true
})
}
},
@ -208,10 +229,10 @@ import assignmentUtils from '../../gradezilla/SISGradePassback/assignmentUtils'
saveAssignments() {
var assignments = assignmentUtils.withOriginalErrorsNotIgnored(this.getAssignments())
var course_id = this.getState().course.id
_.each(assignments, (a) => {
_.each(assignments, a => {
this.assignmentOverrideOrigianlErrorCheck(a)
assignmentUtils.saveAssignmentToCanvas(course_id, a)
});
})
},
postGrades() {
@ -223,20 +244,20 @@ import assignmentUtils from '../../gradezilla/SISGradePassback/assignmentUtils'
getPage() {
var state = this.getState()
if (state.pleaseShowNeedsGradingPage) {
return "needsGrading"
return 'needsGrading'
} else {
var originals = assignmentUtils.withOriginalErrors(this.getAssignments())
var withErrorsCount = _.keys(assignmentUtils.withErrors(this.getAssignments())).length
if (withErrorsCount == 0 && (state.pleaseShowSummaryPage || originals.length == 0)) {
return "summary"
return 'summary'
} else {
return "corrections"
return 'corrections'
}
}
}
})
return store
};
}
export default PostGradesStore

View File

@ -22,13 +22,7 @@ import '../../shared/helpers/createStore'
let assignmentUtils = {
copyFromGradebook(assignment) {
var a = _.pick(assignment, [
"id",
"name",
"due_at",
"needs_grading_count",
"overrides"
])
var a = _.pick(assignment, ['id', 'name', 'due_at', 'needs_grading_count', 'overrides'])
a.please_ignore = false
a.original_error = false
return a
@ -41,8 +35,7 @@ import '../../shared/helpers/createStore'
nameTooLong(a) {
if (_.unescape(a.name).length > 30) {
return true
}
else{
} else {
return false
}
},
@ -50,8 +43,7 @@ import '../../shared/helpers/createStore'
nameEmpty(a) {
if (a.name.length == 0) {
return true
}
else{
} else {
return false
}
},
@ -78,39 +70,101 @@ import '../../shared/helpers/createStore'
// being viewed for that section. If the override is valid make
// original error false so that the override is not shown. Vice versa
// for the invalid override on the assignment.
_.each(assignments, (a) => {
if(a.overrideForThisSection != undefined && a.recentlyUpdated != undefined && a.recentlyUpdated == true && a.overrideForThisSection.due_at != null){a.original_error = false}
else if(a.overrideForThisSection != undefined && a.recentlyUpdated != undefined && a.recentlyUpdated == false && a.overrideForThisSection.due_at == null){a.original_error = true}
_.each(assignments, a => {
if (
a.overrideForThisSection != undefined &&
a.recentlyUpdated != undefined &&
a.recentlyUpdated == true &&
a.overrideForThisSection.due_at != null
) {
a.original_error = false
} else if (
a.overrideForThisSection != undefined &&
a.recentlyUpdated != undefined &&
a.recentlyUpdated == false &&
a.overrideForThisSection.due_at == null
) {
a.original_error = true
}
//for handling original error detection of a valid override for one section and an invalid override for another section
else if(a.overrideForThisSection != undefined && a.overrideForThisSection.due_at != null && !assignmentUtils.noDueDateForEveryoneElseOverride(a) && a.recentlyUpdated == false && a.hadOriginalErrors == false){a.original_error = false}
else if (
a.overrideForThisSection != undefined &&
a.overrideForThisSection.due_at != null &&
!assignmentUtils.noDueDateForEveryoneElseOverride(a) &&
a.recentlyUpdated == false &&
a.hadOriginalErrors == false
) {
a.original_error = false
}
//for handling original error detection of a valid override for one section and the EveryoneElse "override" scenario
else if(a.overrideForThisSection != undefined && a.overrideForThisSection.due_at != null && assignmentUtils.noDueDateForEveryoneElseOverride(a) && a.currentlySelected.id.toString() == a.overrideForThisSection.course_section_id && a.recentlyUpdated == false && a.hadOriginalErrors == false){a.original_error = false}
else if (
a.overrideForThisSection != undefined &&
a.overrideForThisSection.due_at != null &&
assignmentUtils.noDueDateForEveryoneElseOverride(a) &&
a.currentlySelected.id.toString() == a.overrideForThisSection.course_section_id &&
a.recentlyUpdated == false &&
a.hadOriginalErrors == false
) {
a.original_error = false
}
//for handling original error detection of an override for one section and the EveryoneElse "override" scenario but the second section is currentlySelected and IS NOT valid
else if(a.overrideForThisSection == undefined && assignmentUtils.noDueDateForEveryoneElseOverride(a) && a.due_at == null && a.currentlySelected.id.toString() == a.selectedSectionForEveryone){a.original_error = true}
else if (
a.overrideForThisSection == undefined &&
assignmentUtils.noDueDateForEveryoneElseOverride(a) &&
a.due_at == null &&
a.currentlySelected.id.toString() == a.selectedSectionForEveryone
) {
a.original_error = true
}
//for handling original error detection of an override for one section and the EveryoneElse "override" scenario but the second section is currentlySelected and IS valid
else if(a.overrideForThisSection == undefined && a.due_at != null && a.currentlySelected.id.toString() == a.selectedSectionForEveryone && a.hadOriginalErrors == false){a.original_error = false}
else if (
a.overrideForThisSection == undefined &&
a.due_at != null &&
a.currentlySelected.id.toString() == a.selectedSectionForEveryone &&
a.hadOriginalErrors == false
) {
a.original_error = false
}
//for handling original error detection of an "override" in the 'EveryoneElse "override" scenario but the course is currentlySelected and IS NOT valid
else if(a.overrideForThisSection == undefined && assignmentUtils.noDueDateForEveryoneElseOverride(a) && a.due_at == null && a.currentlySelected.type == 'course' && a.currentlySelected.id.toString() != a.selectedSectionForEveryone){a.original_error = true}
else if (
a.overrideForThisSection == undefined &&
assignmentUtils.noDueDateForEveryoneElseOverride(a) &&
a.due_at == null &&
a.currentlySelected.type == 'course' &&
a.currentlySelected.id.toString() != a.selectedSectionForEveryone
) {
a.original_error = true
}
//for handling original error detection of an "override" in the 'EveryoneElse "override" scenario but the course is currentlySelected and IS valid
else if(a.overrideForThisSection == undefined && a.due_at != null && a.currentlySelected.type == 'course' && a.currentlySelected.id.toString() != a.selectedSectionForEveryone && a.hadOriginalErrors == false){a.original_error = false}
});
return _.filter(assignments, (a) => a.original_error && !a.please_ignore)
else if (
a.overrideForThisSection == undefined &&
a.due_at != null &&
a.currentlySelected.type == 'course' &&
a.currentlySelected.id.toString() != a.selectedSectionForEveryone &&
a.hadOriginalErrors == false
) {
a.original_error = false
}
})
return _.filter(assignments, a => a.original_error && !a.please_ignore)
},
withOriginalErrorsNotIgnored(assignments) {
return _.filter(assignments, function(a){ return (a.original_error || a.hadOriginalErrors) && !a.please_ignore})
return _.filter(assignments, function(a) {
return (a.original_error || a.hadOriginalErrors) && !a.please_ignore
})
},
withErrors(assignments) {
return _.filter(assignments, (a) => assignmentUtils.hasError(assignments, a))
return _.filter(assignments, a => assignmentUtils.hasError(assignments, a))
},
notIgnored(assignments) {
return _.filter(assignments, (a) => !a.please_ignore)
return _.filter(assignments, a => !a.please_ignore)
},
needsGrading(assignments) {
return _.filter(assignments, (a) => a.needs_grading_count > 0)
return _.filter(assignments, a => a.needs_grading_count > 0)
},
hasError(assignments, a) {
@ -132,22 +186,51 @@ import '../../shared/helpers/createStore'
////Override missing due_at
var has_this_override = a.overrideForThisSection != undefined
if(has_this_override && a.overrideForThisSection.due_at == null && a.currentlySelected.id.toString() == a.overrideForThisSection.course_section_id) return true
if (
has_this_override &&
a.overrideForThisSection.due_at == null &&
a.currentlySelected.id.toString() == a.overrideForThisSection.course_section_id
)
return true
////Override missing due_at while currentlySelecteed is at the course level
if(has_this_override && a.overrideForThisSection.due_at == null && a.currentlySelected.id.toString() != a.overrideForThisSection.course_section_id) return true
if (
has_this_override &&
a.overrideForThisSection.due_at == null &&
a.currentlySelected.id.toString() != a.overrideForThisSection.course_section_id
)
return true
////Has one override and another override for 'Everyone Else'
////
////The override for 'Everyone Else' isn't really an override and references
////the assignments actual due_at. So we must check for this behavior
if(assignmentUtils.noDueDateForEveryoneElseOverride(a) && a.currentlySelected != undefined && a.overrideForThisSection != undefined && a.currentlySelected.id.toString() != a.overrideForThisSection.course_section_id) return true
if (
assignmentUtils.noDueDateForEveryoneElseOverride(a) &&
a.currentlySelected != undefined &&
a.overrideForThisSection != undefined &&
a.currentlySelected.id.toString() != a.overrideForThisSection.course_section_id
)
return true
////Has only one override but the section that is currently selected does not have an override thus causing the assignment to have due_at that is null making it invalid
if(assignmentUtils.noDueDateForEveryoneElseOverride(a) && a.overrideForThisSection == undefined && a.currentlySelected != undefined && a.currentlySelected.id.toString() == a.selectedSectionForEveryone) return true
if (
assignmentUtils.noDueDateForEveryoneElseOverride(a) &&
a.overrideForThisSection == undefined &&
a.currentlySelected != undefined &&
a.currentlySelected.id.toString() == a.selectedSectionForEveryone
)
return true
////'Everyone Else' scenario and the course is currentlySelected but due_at is null making it invalid
if(assignmentUtils.noDueDateForEveryoneElseOverride(a) && a.overrideForThisSection == undefined && a.currentlySelected != undefined && a.currentlySelected.type == 'course' && a.currentlySelected.id.toString() != a.selectedSectionForEveryone) return true
if (
assignmentUtils.noDueDateForEveryoneElseOverride(a) &&
a.overrideForThisSection == undefined &&
a.currentlySelected != undefined &&
a.currentlySelected.type == 'course' &&
a.currentlySelected.id.toString() != a.selectedSectionForEveryone
)
return true
////Passes all tests, looks good.
return false
@ -159,22 +242,37 @@ import '../../shared/helpers/createStore'
saveAssignmentToCanvas(course_id, assignment) {
// if the date on an override is being updated confirm by checking if the due_at is an object
if(assignment.overrideForThisSection != undefined && typeof(assignment.overrideForThisSection.due_at) == "object") {
if (
assignment.overrideForThisSection != undefined &&
typeof assignment.overrideForThisSection.due_at == 'object'
) {
//allows the validation process to determine when it has been updated and can display the correct page
assignment.hadOriginalErrors = false
var url = '/api/v1/courses/' + course_id + '/assignments/' + assignment.id + '/overrides/' + assignment.overrideForThisSection.id
var url =
'/api/v1/courses/' +
course_id +
'/assignments/' +
assignment.id +
'/overrides/' +
assignment.overrideForThisSection.id
//sets up form data to allow a single override to be updated
var fd = new FormData();
fd.append( 'assignment_override[due_at]', assignment.overrideForThisSection.due_at.toISOString() )
var fd = new FormData()
fd.append(
'assignment_override[due_at]',
assignment.overrideForThisSection.due_at.toISOString()
)
$.ajax(url, {
type: 'PUT',
data: fd,
processData: false,
contentType: false,
error: (err) => {
var msg = 'An error occurred saving assignment override, (' + assignment.overrideForThisSection.id + '). '
msg += "HTTP Error " + data.status + " : " + data.statusText
error: err => {
var msg =
'An error occurred saving assignment override, (' +
assignment.overrideForThisSection.id +
'). '
msg += 'HTTP Error ' + data.status + ' : ' + data.statusText
$.flashError(msg)
}
})
@ -182,68 +280,70 @@ import '../../shared/helpers/createStore'
// that was just set AND the naming conflict is fixed we must also update the assignment
// to mock natural behavior to the user so that the naming conflict does not appear again
url = '/api/v1/courses/' + course_id + '/assignments/' + assignment.id
data = { assignment: {
data = {
assignment: {
name: assignment.name,
due_at: assignment.due_at
}}
}
}
$.ajax(url, {
type: 'PUT',
data: JSON.stringify(data),
contentType: 'application/json; charset=utf-8',
error: (err) => {
error: err => {
var msg = 'An error occurred saving assignment (' + assignment.id + '). '
msg += "HTTP Error " + data.status + " : " + data.statusText
msg += 'HTTP Error ' + data.status + ' : ' + data.statusText
$.flashError(msg)
}
})
}
else {
} else {
//allows the validation process to determine when it has been updated and can display the correct page
assignment.hadOriginalErrors = false
var url = '/api/v1/courses/' + course_id + '/assignments/' + assignment.id
var data = { assignment: {
var data = {
assignment: {
name: assignment.name,
due_at: assignment.due_at
}}
}
}
$.ajax(url, {
type: 'PUT',
data: JSON.stringify(data),
contentType: 'application/json; charset=utf-8',
error: (err) => {
error: err => {
var msg = 'An error occurred saving assignment (' + assignment.id + '). '
msg += "HTTP Error " + data.status + " : " + data.statusText
msg += 'HTTP Error ' + data.status + ' : ' + data.statusText
$.flashError(msg)
}
})
}
},
// Sends a post-grades request to Canvas that is then forwarded to SIS App.
// Expects a list of assignments that will later be queried for grades via
// SIS App's workers
postGradesThroughCanvas(selected, assignments) {
var url = "/api/v1/" + selected.type + "s/" + selected.id + "/post_grades/"
var data = { assignments: _.map(assignments, (assignment) => assignment.id) }
var url = '/api/v1/' + selected.type + 's/' + selected.id + '/post_grades/'
var data = {assignments: _.map(assignments, assignment => assignment.id)}
$.ajax(url, {
type: 'POST',
data: JSON.stringify(data),
contentType: 'application/json; charset=utf-8',
success: (msg) =>{
success: msg => {
if (msg.error) {
$.flashError(msg.error)
} else {
$.flashMessage(msg.message)
}
},
error: (err) => {
var msg = 'An error occurred posting grades for (' + selected.type + ' : ' + selected.id +'). '
msg += "HTTP Error " + data.status + " : " + data.statusText
error: err => {
var msg =
'An error occurred posting grades for (' + selected.type + ' : ' + selected.id + '). '
msg += 'HTTP Error ' + data.status + ' : ' + data.statusText
$.flashError(msg)
}
})
}
};
}
export default assignmentUtils

View File

@ -16,66 +16,88 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import _ from 'underscore';
import GradingPeriodsHelper from '../grading/helpers/GradingPeriodsHelper';
import _ from 'underscore'
import GradingPeriodsHelper from '../grading/helpers/GradingPeriodsHelper'
function submissionGradingPeriodInformation(assignment, student) {
const submissionInfo = assignment.effectiveDueDates[student.id] || {};
const submissionInfo = assignment.effectiveDueDates[student.id] || {}
return {
gradingPeriodID: submissionInfo.grading_period_id,
inClosedGradingPeriod: submissionInfo.in_closed_grading_period
};
}
}
function hiddenFromStudent(assignment, student) {
if (assignment.only_visible_to_overrides) {
return !_.contains(assignment.assignment_visibility, student.id);
return !_.contains(assignment.assignment_visibility, student.id)
}
return false
}
function gradingPeriodInfoForCell(assignment, student, selectedGradingPeriodID) {
const specificPeriodSelected = !GradingPeriodsHelper.isAllGradingPeriods(selectedGradingPeriodID);
const { gradingPeriodID, inClosedGradingPeriod } = submissionGradingPeriodInformation(assignment, student);
const inNoGradingPeriod = !gradingPeriodID;
const inOtherGradingPeriod = !!gradingPeriodID && specificPeriodSelected &&
selectedGradingPeriodID !== gradingPeriodID;
const specificPeriodSelected = !GradingPeriodsHelper.isAllGradingPeriods(selectedGradingPeriodID)
const {gradingPeriodID, inClosedGradingPeriod} = submissionGradingPeriodInformation(
assignment,
student
)
const inNoGradingPeriod = !gradingPeriodID
const inOtherGradingPeriod =
!!gradingPeriodID && specificPeriodSelected && selectedGradingPeriodID !== gradingPeriodID
return {
inNoGradingPeriod,
inOtherGradingPeriod,
inClosedGradingPeriod
};
}
}
function cellMappingsForMultipleGradingPeriods (assignment, student, selectedGradingPeriodID, isAdmin) {
const specificPeriodSelected = !GradingPeriodsHelper.isAllGradingPeriods(selectedGradingPeriodID);
const { gradingPeriodID, inClosedGradingPeriod } = submissionGradingPeriodInformation(assignment, student);
const gradingPeriodInfo = gradingPeriodInfoForCell(assignment, student, selectedGradingPeriodID);
let cellMapping;
function cellMappingsForMultipleGradingPeriods(
assignment,
student,
selectedGradingPeriodID,
isAdmin
) {
const specificPeriodSelected = !GradingPeriodsHelper.isAllGradingPeriods(selectedGradingPeriodID)
const {gradingPeriodID, inClosedGradingPeriod} = submissionGradingPeriodInformation(
assignment,
student
)
const gradingPeriodInfo = gradingPeriodInfoForCell(assignment, student, selectedGradingPeriodID)
let cellMapping
if (specificPeriodSelected && (!gradingPeriodID || selectedGradingPeriodID !== gradingPeriodID)) {
cellMapping = { locked: true, hideGrade: true };
cellMapping = {locked: true, hideGrade: true}
} else if (!isAdmin && inClosedGradingPeriod) {
cellMapping = { locked: true, hideGrade: false };
cellMapping = {locked: true, hideGrade: false}
} else {
cellMapping = { locked: false, hideGrade: false };
cellMapping = {locked: false, hideGrade: false}
}
return { ...cellMapping, ...gradingPeriodInfo };
return {...cellMapping, ...gradingPeriodInfo}
}
function cellMapForSubmission (assignment, student, hasGradingPeriods, selectedGradingPeriodID, isAdmin) {
function cellMapForSubmission(
assignment,
student,
hasGradingPeriods,
selectedGradingPeriodID,
isAdmin
) {
if (!assignment.published || assignment.anonymize_students) {
return { locked: true, hideGrade: true };
return {locked: true, hideGrade: true}
} else if (assignment.moderated_grading && !assignment.grades_published) {
return { locked: true, hideGrade: false };
return {locked: true, hideGrade: false}
} else if (hiddenFromStudent(assignment, student)) {
return { locked: true, hideGrade: true };
return {locked: true, hideGrade: true}
} else if (hasGradingPeriods) {
return cellMappingsForMultipleGradingPeriods(assignment, student, selectedGradingPeriodID, isAdmin);
return cellMappingsForMultipleGradingPeriods(
assignment,
student,
selectedGradingPeriodID,
isAdmin
)
} else {
return { locked: false, hideGrade: false };
return {locked: false, hideGrade: false}
}
}
@ -87,53 +109,54 @@ function missingSubmission (student, assignment) {
late: false,
missing: false,
seconds_late: 0
};
const dueDates = assignment.effectiveDueDates[student.id] || {};
if (dueDates.due_at != null && new Date(dueDates.due_at) < new Date()) {
submission.missing = true;
}
return submission;
const dueDates = assignment.effectiveDueDates[student.id] || {}
if (dueDates.due_at != null && new Date(dueDates.due_at) < new Date()) {
submission.missing = true
}
return submission
}
class SubmissionStateMap {
constructor({hasGradingPeriods, selectedGradingPeriodID, isAdmin}) {
this.hasGradingPeriods = hasGradingPeriods;
this.selectedGradingPeriodID = selectedGradingPeriodID;
this.isAdmin = isAdmin;
this.submissionCellMap = {};
this.submissionMap = {};
this.hasGradingPeriods = hasGradingPeriods
this.selectedGradingPeriodID = selectedGradingPeriodID
this.isAdmin = isAdmin
this.submissionCellMap = {}
this.submissionMap = {}
}
setup(students, assignments) {
students.forEach((student) => {
this.submissionCellMap[student.id] = {};
this.submissionMap[student.id] = {};
_.each(assignments, (assignment) => {
this.setSubmissionCellState(student, assignment, student[`assignment_${assignment.id}`]);
});
});
students.forEach(student => {
this.submissionCellMap[student.id] = {}
this.submissionMap[student.id] = {}
_.each(assignments, assignment => {
this.setSubmissionCellState(student, assignment, student[`assignment_${assignment.id}`])
})
})
}
setSubmissionCellState(student, assignment, submission) {
this.submissionMap[student.id][assignment.id] = submission || missingSubmission(student, assignment);
this.submissionMap[student.id][assignment.id] =
submission || missingSubmission(student, assignment)
const params = [
assignment,
student,
this.hasGradingPeriods,
this.selectedGradingPeriodID,
this.isAdmin
];
]
this.submissionCellMap[student.id][assignment.id] = cellMapForSubmission(...params);
this.submissionCellMap[student.id][assignment.id] = cellMapForSubmission(...params)
}
getSubmission(userId, assignmentId) {
return (this.submissionMap[userId] || {})[assignmentId];
return (this.submissionMap[userId] || {})[assignmentId]
}
getSubmissionState({user_id: userId, assignment_id: assignmentId}) {
return (this.submissionCellMap[userId] || {})[assignmentId];
return (this.submissionCellMap[userId] || {})[assignmentId]
}
}
export default SubmissionStateMap;
export default SubmissionStateMap

View File

@ -23,19 +23,28 @@ import 'compiled/jquery.rails_flash_notifications'
const CurveGradesDialogManager = {
createCurveGradesAction(assignment, students, {isAdmin, contextUrl, submissionsLoaded} = {}) {
const { grading_type: gradingType, points_possible: pointsPossible } = assignment;
const {grading_type: gradingType, points_possible: pointsPossible} = assignment
return {
isDisabled: !submissionsLoaded || gradingType === 'pass_fail' || pointsPossible == null || pointsPossible === 0,
isDisabled:
!submissionsLoaded ||
gradingType === 'pass_fail' ||
pointsPossible == null ||
pointsPossible === 0,
onSelect (onClose) { // eslint-disable-line consistent-return
onSelect(onClose) {
// eslint-disable-line consistent-return
if (!isAdmin && assignment.inClosedGradingPeriod) {
return $.flashError(I18n.t('Unable to curve grades because this assignment is due in a closed ' +
'grading period for at least one student'));
return $.flashError(
I18n.t(
'Unable to curve grades because this assignment is due in a closed ' +
'grading period for at least one student'
)
)
}
const dialog = new CurveGradesDialog({assignment, students, context_url: contextUrl})
dialog.show(onClose)
}
const dialog = new CurveGradesDialog({assignment, students, context_url: contextUrl});
dialog.show(onClose);
}
};
}
}
export default CurveGradesDialogManager

View File

@ -77,7 +77,7 @@ export function createGradebook(options = {}) {
}
export function setFixtureHtml($fixture) {
return $fixture.innerHTML = `
return ($fixture.innerHTML = `
<div id="application">
<div id="wrapper">
<div data-component="GridColor"></div>
@ -98,7 +98,7 @@ export function setFixtureHtml($fixture) {
<div id="gradebook_grid"></div>
</div>
</div>
`
`)
}
export function stubDataLoader() {

View File

@ -16,34 +16,34 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import axios from 'axios';
import I18n from 'i18n!gradebook';
import { underscore } from 'convert_case';
import axios from 'axios'
import I18n from 'i18n!gradebook'
import {underscore} from 'convert_case'
function createTeacherNotesColumn(courseId) {
const url = `/api/v1/courses/${courseId}/custom_gradebook_columns`;
const url = `/api/v1/courses/${courseId}/custom_gradebook_columns`
const data = {
column: {
position: 1,
teacher_notes: true,
title: I18n.t('Notes')
}
};
return axios.post(url, data);
}
return axios.post(url, data)
}
function updateTeacherNotesColumn(courseId, columnId, attr) {
const url = `/api/v1/courses/${courseId}/custom_gradebook_columns/${columnId}`;
return axios.put(url, { column: attr });
const url = `/api/v1/courses/${courseId}/custom_gradebook_columns/${columnId}`
return axios.put(url, {column: attr})
}
function updateSubmission(courseId, assignmentId, userId, submission) {
const url = `/api/v1/courses/${courseId}/assignments/${assignmentId}/submissions/${userId}`;
return axios.put(url, { submission: underscore(submission), include: ['visibility'] });
const url = `/api/v1/courses/${courseId}/assignments/${assignmentId}/submissions/${userId}`
return axios.put(url, {submission: underscore(submission), include: ['visibility']})
}
export default {
createTeacherNotesColumn,
updateTeacherNotesColumn,
updateSubmission
};
}

View File

@ -16,8 +16,8 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import axios from 'axios';
import { camelize, underscore } from 'convert_case';
import axios from 'axios'
import {camelize, underscore} from 'convert_case'
export const DEFAULT_LATE_POLICY_DATA = Object.freeze({
lateSubmissionDeductionEnabled: false,
@ -28,40 +28,39 @@ export const DEFAULT_LATE_POLICY_DATA = Object.freeze({
missingSubmissionDeductionEnabled: false,
missingSubmissionDeduction: 0,
newRecord: true
});
})
function camelizeLatePolicyResponseData(latePolicyResponseData) {
const camelizedData = camelize(latePolicyResponseData.late_policy);
return { latePolicy: camelizedData };
const camelizedData = camelize(latePolicyResponseData.late_policy)
return {latePolicy: camelizedData}
}
export function fetchLatePolicy(courseId) {
const url = `/api/v1/courses/${courseId}/late_policy`;
return axios.get(url)
.then(response => (
{ data: camelizeLatePolicyResponseData(response.data) }
))
.catch((error) => {
const url = `/api/v1/courses/${courseId}/late_policy`
return axios
.get(url)
.then(response => ({data: camelizeLatePolicyResponseData(response.data)}))
.catch(error => {
// if we get a 404 then we know the course does not
// currently have a late policy set up
if (error.response && error.response.status === 404) {
return Promise.resolve({ data: { latePolicy: DEFAULT_LATE_POLICY_DATA } });
return Promise.resolve({data: {latePolicy: DEFAULT_LATE_POLICY_DATA}})
} else {
return Promise.reject(error);
return Promise.reject(error)
}
});
})
}
export function createLatePolicy(courseId, latePolicyData) {
const url = `/api/v1/courses/${courseId}/late_policy`;
const data = { late_policy: underscore(latePolicyData) };
return axios.post(url, data).then(response => (
{ data: camelizeLatePolicyResponseData(response.data) }
));
const url = `/api/v1/courses/${courseId}/late_policy`
const data = {late_policy: underscore(latePolicyData)}
return axios
.post(url, data)
.then(response => ({data: camelizeLatePolicyResponseData(response.data)}))
}
export function updateLatePolicy(courseId, latePolicyData) {
const url = `/api/v1/courses/${courseId}/late_policy`;
const data = { late_policy: underscore(latePolicyData) };
return axios.patch(url, data);
const url = `/api/v1/courses/${courseId}/late_policy`
const data = {late_policy: underscore(latePolicyData)}
return axios.patch(url, data)
}

View File

@ -16,8 +16,8 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import axios from 'axios';
import timezone from 'timezone';
import axios from 'axios'
import timezone from 'timezone'
function deserializeComment(comment) {
const baseComment = {
@ -25,10 +25,10 @@ function deserializeComment (comment) {
createdAt: timezone.parse(comment.created_at),
comment: comment.comment,
editedAt: comment.edited_at && timezone.parse(comment.edited_at)
};
}
if (!comment.author) {
return baseComment;
return baseComment
}
return {
@ -37,36 +37,38 @@ function deserializeComment (comment) {
author: comment.author.display_name,
authorAvatarUrl: comment.author.avatar_image_url,
authorUrl: comment.author.html_url
};
}
}
function deserializeComments(comments) {
return comments.map(deserializeComment);
return comments.map(deserializeComment)
}
export function getSubmissionComments(courseId, assignmentId, studentId) {
const commentOptions = { params: { include: 'submission_comments' } };
const url = `/api/v1/courses/${courseId}/assignments/${assignmentId}/submissions/${studentId}`;
return axios.get(url, commentOptions)
.then(response => deserializeComments(response.data.submission_comments));
const commentOptions = {params: {include: 'submission_comments'}}
const url = `/api/v1/courses/${courseId}/assignments/${assignmentId}/submissions/${studentId}`
return axios
.get(url, commentOptions)
.then(response => deserializeComments(response.data.submission_comments))
}
export function createSubmissionComment(courseId, assignmentId, studentId, comment) {
const url = `/api/v1/courses/${courseId}/assignments/${assignmentId}/submissions/${studentId}`;
const data = { group_comment: 0, comment: { text_comment: comment } };
return axios.put(url, data)
.then(response => deserializeComments(response.data.submission_comments));
const url = `/api/v1/courses/${courseId}/assignments/${assignmentId}/submissions/${studentId}`
const data = {group_comment: 0, comment: {text_comment: comment}}
return axios
.put(url, data)
.then(response => deserializeComments(response.data.submission_comments))
}
export function deleteSubmissionComment(commentId) {
const url = `/submission_comments/${commentId}`;
return axios.delete(url);
const url = `/submission_comments/${commentId}`
return axios.delete(url)
}
export function updateSubmissionComment(commentId, comment) {
const url = `/submission_comments/${commentId}`;
const data = { id: commentId, submission_comment: { comment } };
return axios.put(url, data).then(response => (
{ data: deserializeComment(response.data.submission_comment) }
));
const url = `/submission_comments/${commentId}`
const data = {id: commentId, submission_comment: {comment}}
return axios
.put(url, data)
.then(response => ({data: deserializeComment(response.data.submission_comment)}))
}

View File

@ -16,15 +16,15 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import I18n from 'i18n!gradebook';
import I18n from 'i18n!gradebook'
export const filterLabels = {
assignmentGroups: I18n.t('Assignment Groups'),
gradingPeriods: I18n.t('Grading Periods'),
modules: I18n.t('Modules'),
sections: I18n.t('Sections')
};
}
export default {
filterLabels
};
}

View File

@ -16,7 +16,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import Color from 'tinycolor2';
import Color from 'tinycolor2'
export const defaultColors = {
salmon: '#FFE8E5',
@ -29,7 +29,7 @@ export const defaultColors = {
pink: '#F8EAF6',
lavender: '#F0E8EF',
white: '#FFFFFF'
};
}
const defaultStatusColors = {
dropped: defaultColors.orange,
@ -37,15 +37,15 @@ const defaultStatusColors = {
late: defaultColors.blue,
missing: defaultColors.salmon,
resubmitted: defaultColors.green
};
}
export function statusColors(userColors = {}) {
return {
...defaultStatusColors,
...userColors
};
}
}
export function darken(color, percent) {
return Color(color).darken(percent);
return Color(color).darken(percent)
}

View File

@ -16,15 +16,9 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import I18n from 'i18n!gradebook';
import I18n from 'i18n!gradebook'
export const statuses = [
'late',
'missing',
'resubmitted',
'dropped',
'excused'
];
export const statuses = ['late', 'missing', 'resubmitted', 'dropped', 'excused']
export const statusesTitleMap = {
late: I18n.t('Late'),
@ -32,5 +26,4 @@ export const statusesTitleMap = {
resubmitted: I18n.t('Resubmitted'),
dropped: I18n.t('Dropped'),
excused: I18n.t('Excused')
};
}

View File

@ -16,15 +16,15 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import I18n from 'i18n!gradebook';
import I18n from 'i18n!gradebook'
const primaryInfoLabels = {
first_last: I18n.t('First, Last Name'),
last_first: I18n.t('Last, First Name'),
};
last_first: I18n.t('Last, First Name')
}
const primaryInfoKeys = ['first_last', 'last_first'];
const defaultPrimaryInfo = 'first_last';
const primaryInfoKeys = ['first_last', 'last_first']
const defaultPrimaryInfo = 'first_last'
const secondaryInfoLabels = {
section: I18n.t('Section'),
@ -32,18 +32,18 @@ const secondaryInfoLabels = {
integration_id: I18n.t('Integration ID'),
login_id: I18n.t('Login ID'),
none: I18n.t('None')
};
}
const secondaryInfoKeys = ['section', 'sis_id', 'integration_id', 'login_id', 'none'];
const defaultSecondaryInfo = 'none';
const sectionSecondaryInfo = 'section';
const secondaryInfoKeys = ['section', 'sis_id', 'integration_id', 'login_id', 'none']
const defaultSecondaryInfo = 'none'
const sectionSecondaryInfo = 'section'
const enrollmentFilterLabels = {
inactive: I18n.t('Inactive enrollments'),
concluded: I18n.t('Concluded enrollments')
};
}
const enrollmentFilterKeys = ['inactive', 'concluded'];
const enrollmentFilterKeys = ['inactive', 'concluded']
export default {
primaryInfoKeys,
@ -55,4 +55,4 @@ export default {
sectionSecondaryInfo,
enrollmentFilterKeys,
enrollmentFilterLabels
};
}

View File

@ -16,10 +16,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import {
instanceOf,
string
} from 'prop-types';
import {instanceOf, string} from 'prop-types'
const SubmissionTrayCommentPropTypes = {
id: string.isRequired,
@ -29,6 +26,6 @@ const SubmissionTrayCommentPropTypes = {
createdAt: instanceOf(Date).isRequired,
comment: string.isRequired,
editedAt: instanceOf(Date)
};
}
export default SubmissionTrayCommentPropTypes;
export default SubmissionTrayCommentPropTypes

View File

@ -16,7 +16,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import _ from 'lodash';
import _ from 'lodash'
function createStudentPlaceholder(id) {
return {
@ -27,48 +27,48 @@ function createStudentPlaceholder (id) {
isPlaceholder: true,
loaded: false,
sections: []
};
}
}
export default class StudentDatastore {
studentIds = [];
studentIds = []
constructor(userStudentMap, testStudentMap) {
this.userStudentMap = userStudentMap;
this.testStudentMap = testStudentMap;
this.userStudentMap = userStudentMap
this.testStudentMap = testStudentMap
}
listStudentIds() {
return this.studentIds;
return this.studentIds
}
setStudentIds(studentIds) {
this.studentIds = studentIds;
const idsOfStoredStudents = Object.keys(this.userStudentMap);
_.difference(idsOfStoredStudents, studentIds).forEach((removedStudentId) => {
delete this.userStudentMap[removedStudentId];
});
const idsOfStoredTestStudents = Object.keys(this.testStudentMap);
_.difference(idsOfStoredTestStudents, studentIds).forEach((removedStudentId) => {
delete this.testStudentMap[removedStudentId];
});
this.studentIds = studentIds
const idsOfStoredStudents = Object.keys(this.userStudentMap)
_.difference(idsOfStoredStudents, studentIds).forEach(removedStudentId => {
delete this.userStudentMap[removedStudentId]
})
const idsOfStoredTestStudents = Object.keys(this.testStudentMap)
_.difference(idsOfStoredTestStudents, studentIds).forEach(removedStudentId => {
delete this.testStudentMap[removedStudentId]
})
}
addUserStudents(students) {
students.forEach((student) => {
this.userStudentMap[student.id] = student;
});
students.forEach(student => {
this.userStudentMap[student.id] = student
})
}
addTestStudents(students) {
students.forEach((student) => {
this.testStudentMap[student.id] = student;
});
students.forEach(student => {
this.testStudentMap[student.id] = student
})
}
listStudents() {
return this.studentIds.map(id => (
this.userStudentMap[id] || this.testStudentMap[id] || createStudentPlaceholder(id)
));
return this.studentIds.map(
id => this.userStudentMap[id] || this.testStudentMap[id] || createStudentPlaceholder(id)
)
}
}

View File

@ -22,22 +22,24 @@ import 'jquery.instructure_misc_helpers'
class DownloadSubmissionsDialogManager {
constructor(assignment, downloadUrlTemplate, submissionsDownloading) {
this.assignment = assignment;
this.downloadUrl = $.replaceTags(downloadUrlTemplate, 'assignment_id', assignment.id);
this.showDialog = this.showDialog.bind(this);
this.validSubmissionTypes = ['online_upload', 'online_text_entry', 'online_url'];
this.submissionsDownloading = submissionsDownloading;
this.assignment = assignment
this.downloadUrl = $.replaceTags(downloadUrlTemplate, 'assignment_id', assignment.id)
this.showDialog = this.showDialog.bind(this)
this.validSubmissionTypes = ['online_upload', 'online_text_entry', 'online_url']
this.submissionsDownloading = submissionsDownloading
}
isDialogEnabled() {
return this.assignment.submission_types && this.assignment.submission_types.some(
t => this.validSubmissionTypes.includes(t)
) && this.assignment.has_submitted_submissions;
return (
this.assignment.submission_types &&
this.assignment.submission_types.some(t => this.validSubmissionTypes.includes(t)) &&
this.assignment.has_submitted_submissions
)
}
showDialog(cb) {
this.submissionsDownloading(this.assignment.id);
INST.downloadSubmissions(this.downloadUrl, cb);
this.submissionsDownloading(this.assignment.id)
INST.downloadSubmissions(this.downloadUrl, cb)
}
}

View File

@ -22,7 +22,7 @@ const gradingTypeOptionMap = {
pass_fail: ['passFail'],
percent: ['points', 'percent'],
points: ['points', 'percent']
};
}
const gradingTypeDefaultOptionMap = {
gpa_scale: 'gradingScheme',
@ -30,12 +30,12 @@ const gradingTypeDefaultOptionMap = {
pass_fail: 'passFail',
percent: 'percent',
points: 'points'
};
}
export function defaultOptionForGradingType(gradingType) {
return gradingTypeDefaultOptionMap[gradingType] || null;
return gradingTypeDefaultOptionMap[gradingType] || null
}
export function optionsForGradingType(gradingType) {
return gradingTypeOptionMap[gradingType] || [];
return gradingTypeOptionMap[gradingType] || []
}

View File

@ -20,115 +20,125 @@ import axios from 'axios'
import I18n from 'i18n!gradebook'
class GradebookExportManager {
static DEFAULT_POLLING_INTERVAL = 2000;
static DEFAULT_MONITORING_BASE_URL = '/api/v1/progress';
static DEFAULT_ATTACHMENT_BASE_URL = '/api/v1/users';
static DEFAULT_POLLING_INTERVAL = 2000
static DEFAULT_MONITORING_BASE_URL = '/api/v1/progress'
static DEFAULT_ATTACHMENT_BASE_URL = '/api/v1/users'
static exportCompleted(workflowState) {
return workflowState === 'completed';
return workflowState === 'completed'
}
// Returns false if the workflowState is 'failed' or an unknown state
static exportFailed(workflowState) {
if (workflowState === 'failed') return true;
if (workflowState === 'failed') return true
return !['completed', 'queued', 'running'].includes(workflowState);
return !['completed', 'queued', 'running'].includes(workflowState)
}
constructor (exportingUrl, currentUserId, existingExport, pollingInterval = GradebookExportManager.DEFAULT_POLLING_INTERVAL) {
this.pollingInterval = pollingInterval;
constructor(
exportingUrl,
currentUserId,
existingExport,
pollingInterval = GradebookExportManager.DEFAULT_POLLING_INTERVAL
) {
this.pollingInterval = pollingInterval
this.exportingUrl = exportingUrl;
this.monitoringBaseUrl = GradebookExportManager.DEFAULT_MONITORING_BASE_URL;
this.attachmentBaseUrl = `${GradebookExportManager.DEFAULT_ATTACHMENT_BASE_URL}/${currentUserId}/files`;
this.currentUserId = currentUserId;
this.exportingUrl = exportingUrl
this.monitoringBaseUrl = GradebookExportManager.DEFAULT_MONITORING_BASE_URL
this.attachmentBaseUrl = `${
GradebookExportManager.DEFAULT_ATTACHMENT_BASE_URL
}/${currentUserId}/files`
this.currentUserId = currentUserId
if (existingExport) {
const workflowState = existingExport.workflowState;
const workflowState = existingExport.workflowState
if (workflowState !== 'completed' && workflowState !== 'failed') {
this.export = existingExport;
this.export = existingExport
}
}
}
monitoringUrl() {
if (!(this.export && this.export.progressId)) return undefined;
if (!(this.export && this.export.progressId)) return undefined
return `${this.monitoringBaseUrl}/${this.export.progressId}`;
return `${this.monitoringBaseUrl}/${this.export.progressId}`
}
attachmentUrl() {
if (!(this.attachmentBaseUrl && this.export && this.export.attachmentId)) return undefined;
if (!(this.attachmentBaseUrl && this.export && this.export.attachmentId)) return undefined
return `${this.attachmentBaseUrl}/${this.export.attachmentId}`;
return `${this.attachmentBaseUrl}/${this.export.attachmentId}`
}
clearMonitor() {
if (this.exportStatusPoll) {
window.clearInterval(this.exportStatusPoll);
this.exportStatusPoll = null;
window.clearInterval(this.exportStatusPoll)
this.exportStatusPoll = null
}
}
monitorExport(resolve, reject) {
if (!this.monitoringUrl()) {
this.export = undefined;
this.export = undefined
reject(I18n.t('No way to monitor gradebook exports provided!'));
reject(I18n.t('No way to monitor gradebook exports provided!'))
}
this.exportStatusPoll = window.setInterval(() => {
axios.get(this.monitoringUrl()).then((response) => {
const workflowState = response.data.workflow_state;
axios.get(this.monitoringUrl()).then(response => {
const workflowState = response.data.workflow_state
if (GradebookExportManager.exportCompleted(workflowState)) {
this.clearMonitor();
this.clearMonitor()
// Export is complete => let's get the attachment url
axios.get(this.attachmentUrl()).then((attachmentResponse) => {
axios
.get(this.attachmentUrl())
.then(attachmentResponse => {
const resolution = {
attachmentUrl: attachmentResponse.data.url,
updatedAt: attachmentResponse.data.updated_at
};
this.export = undefined;
resolve(resolution);
}).catch((error) => {
reject(error);
});
} else if (GradebookExportManager.exportFailed(workflowState)) {
this.clearMonitor();
reject(I18n.t('Error exporting gradebook: %{msg}', { msg: response.data.message }));
}
});
}, this.pollingInterval);
this.export = undefined
resolve(resolution)
})
.catch(error => {
reject(error)
})
} else if (GradebookExportManager.exportFailed(workflowState)) {
this.clearMonitor()
reject(I18n.t('Error exporting gradebook: %{msg}', {msg: response.data.message}))
}
})
}, this.pollingInterval)
}
startExport(gradingPeriodId) {
if (!this.exportingUrl) {
return Promise.reject(I18n.t('No way to export gradebooks provided!'));
return Promise.reject(I18n.t('No way to export gradebooks provided!'))
}
if (this.export) {
// We already have an ongoing export, ignoring this call to start a new one
return Promise.reject(I18n.t('An export is already in progress.'));
return Promise.reject(I18n.t('An export is already in progress.'))
}
const params = {
grading_period_id: gradingPeriodId
};
}
return axios.get(this.exportingUrl, { params }).then((response) => {
return axios.get(this.exportingUrl, {params}).then(response => {
this.export = {
progressId: response.data.progress_id,
attachmentId: response.data.attachment_id
};
}
return new Promise(this.monitorExport.bind(this));
});
return new Promise(this.monitorExport.bind(this))
})
}
}

View File

@ -24,54 +24,54 @@ import 'jquery.instructure_misc_helpers'
class ReuploadSubmissionsDialogManager {
constructor(assignment, reuploadUrlTemplate) {
this.assignment = assignment;
this.reuploadUrl = $.replaceTags(reuploadUrlTemplate, 'assignment_id', assignment.id);
this.showDialog = this.showDialog.bind(this);
this.assignment = assignment
this.reuploadUrl = $.replaceTags(reuploadUrlTemplate, 'assignment_id', assignment.id)
this.showDialog = this.showDialog.bind(this)
}
isDialogEnabled() {
return this.assignment.hasDownloadedSubmissions;
return this.assignment.hasDownloadedSubmissions
}
getReuploadForm(cb) {
if (ReuploadSubmissionsDialogManager.reuploadForm) {
return ReuploadSubmissionsDialogManager.reuploadForm;
return ReuploadSubmissionsDialogManager.reuploadForm
}
ReuploadSubmissionsDialogManager.reuploadForm = $(
re_upload_submissions_form({authenticityToken: authenticity_token()})
).dialog(
{
)
.dialog({
width: 400,
modal: true,
resizable: false,
autoOpen: false,
close: () => {
if (typeof cb === 'function') {
cb();
cb()
}
}
}
).submit(function () {
const data = $(this).getFormData();
let submitForm = true;
})
.submit(function() {
const data = $(this).getFormData()
let submitForm = true
if (!data.submissions_zip) {
submitForm = false;
submitForm = false
} else if (!data.submissions_zip.match(/\.zip$/)) {
$(this).formErrors({ submissions_zip: I18n.t('Please upload files as a .zip') });
submitForm = false;
$(this).formErrors({submissions_zip: I18n.t('Please upload files as a .zip')})
submitForm = false
}
return submitForm;
});
return submitForm
})
return ReuploadSubmissionsDialogManager.reuploadForm;
return ReuploadSubmissionsDialogManager.reuploadForm
}
showDialog(cb) {
const form = this.getReuploadForm(cb);
form.attr('action', this.reuploadUrl).dialog('open');
const form = this.getReuploadForm(cb)
form.attr('action', this.reuploadUrl).dialog('open')
}
}

View File

@ -22,15 +22,22 @@ import SetDefaultGradeDialog from 'compiled/gradezilla/SetDefaultGradeDialog'
import 'compiled/jquery.rails_flash_notifications'
class SetDefaultGradeDialogManager {
constructor (assignment, students, contextId, selectedSection, isAdmin = false, submissionsLoaded = false) {
this.assignment = assignment;
this.students = students;
this.contextId = contextId;
this.selectedSection = selectedSection;
this.isAdmin = isAdmin;
this.submissionsLoaded = submissionsLoaded;
constructor(
assignment,
students,
contextId,
selectedSection,
isAdmin = false,
submissionsLoaded = false
) {
this.assignment = assignment
this.students = students
this.contextId = contextId
this.selectedSection = selectedSection
this.isAdmin = isAdmin
this.submissionsLoaded = submissionsLoaded
this.showDialog = this.showDialog.bind(this);
this.showDialog = this.showDialog.bind(this)
}
getSetDefaultGradeDialogOptions() {
@ -38,23 +45,27 @@ import 'compiled/jquery.rails_flash_notifications'
assignment: this.assignment,
students: this.students,
context_id: this.contextId,
selected_section: this.selectedSection,
};
selected_section: this.selectedSection
}
}
showDialog(cb) {
if (this.isAdmin || !this.assignment.inClosedGradingPeriod) {
const dialog = new SetDefaultGradeDialog(this.getSetDefaultGradeDialogOptions());
const dialog = new SetDefaultGradeDialog(this.getSetDefaultGradeDialogOptions())
dialog.show(cb);
dialog.show(cb)
} else {
$.flashError(I18n.t('Unable to set default grade because this ' +
'assignment is due in a closed grading period for at least one student'));
$.flashError(
I18n.t(
'Unable to set default grade because this ' +
'assignment is due in a closed grading period for at least one student'
)
)
}
}
isDialogEnabled() {
return this.submissionsLoaded;
return this.submissionsLoaded
}
}

View File

@ -16,14 +16,16 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import $ from 'jquery';
import $ from 'jquery'
export function getWidth(text) {
let $textMeasure = $('#text-measure');
let $textMeasure = $('#text-measure')
if (!$textMeasure.length) {
$textMeasure = $('<span id="text-measure" style="padding: 10px; display: none;" />').appendTo('#content');
$textMeasure = $('<span id="text-measure" style="padding: 10px; display: none;" />').appendTo(
'#content'
)
}
return $textMeasure.text(text).outerWidth();
return $textMeasure.text(text).outerWidth()
}
export default {

View File

@ -19,69 +19,81 @@
import _ from 'underscore'
function uniqueEffectiveDueDates(assignment) {
const dueDates = _.map(assignment.effectiveDueDates, function(dueDateInfo) {
const dueAt = dueDateInfo.due_at;
return dueAt ? new Date(dueAt) : dueAt;
});
const dueAt = dueDateInfo.due_at
return dueAt ? new Date(dueAt) : dueAt
})
return _.uniq(dueDates, date => date ? date.toString() : date);
return _.uniq(dueDates, date => (date ? date.toString() : date))
}
function getDueDateFromAssignment(assignment) {
if (assignment.due_at) {
return new Date(assignment.due_at);
return new Date(assignment.due_at)
}
const dueDates = uniqueEffectiveDueDates(assignment);
return dueDates.length === 1 ? dueDates[0] : null;
const dueDates = uniqueEffectiveDueDates(assignment)
return dueDates.length === 1 ? dueDates[0] : null
}
const assignmentHelper = {
compareByDueDate(a, b) {
let aDate = getDueDateFromAssignment(a);
let bDate = getDueDateFromAssignment(b);
const aDateIsNull = _.isNull(aDate);
const bDateIsNull = _.isNull(bDate);
if (aDateIsNull && !bDateIsNull) { return 1 }
if (!aDateIsNull && bDateIsNull) { return -1 }
let aDate = getDueDateFromAssignment(a)
let bDate = getDueDateFromAssignment(b)
const aDateIsNull = _.isNull(aDate)
const bDateIsNull = _.isNull(bDate)
if (aDateIsNull && !bDateIsNull) {
return 1
}
if (!aDateIsNull && bDateIsNull) {
return -1
}
if (aDateIsNull && bDateIsNull) {
const aHasMultipleDates = this.hasMultipleDueDates(a);
const bHasMultipleDates = this.hasMultipleDueDates(b);
if (aHasMultipleDates && !bHasMultipleDates) { return -1 }
if (!aHasMultipleDates && bHasMultipleDates) { return 1 }
const aHasMultipleDates = this.hasMultipleDueDates(a)
const bHasMultipleDates = this.hasMultipleDueDates(b)
if (aHasMultipleDates && !bHasMultipleDates) {
return -1
}
aDate = +aDate;
bDate = +bDate;
if (!aHasMultipleDates && bHasMultipleDates) {
return 1
}
}
aDate = +aDate
bDate = +bDate
if (aDate === bDate) {
const aName = a.name.toLowerCase();
const bName = b.name.toLowerCase();
if (aName === bName) { return 0 }
return aName > bName ? 1 : -1;
const aName = a.name.toLowerCase()
const bName = b.name.toLowerCase()
if (aName === bName) {
return 0
}
return aDate - bDate;
return aName > bName ? 1 : -1
}
return aDate - bDate
},
hasMultipleDueDates(assignment) {
return uniqueEffectiveDueDates(assignment).length > 1;
return uniqueEffectiveDueDates(assignment).length > 1
},
getComparator(arrangeBy) {
if (arrangeBy === 'due_date') {
return this.compareByDueDate.bind(this);
return this.compareByDueDate.bind(this)
}
if (arrangeBy === 'assignment_group') {
return this.compareByAssignmentGroup.bind(this);
return this.compareByAssignmentGroup.bind(this)
}
},
compareByAssignmentGroup(a, b) {
const diffOfAssignmentGroupPosition = a.assignment_group_position - b.assignment_group_position;
const diffOfAssignmentGroupPosition = a.assignment_group_position - b.assignment_group_position
if (diffOfAssignmentGroupPosition === 0) {
const diffOfAssignmentPosition = a.position - b.position;
if (diffOfAssignmentPosition === 0) { return 0 }
return diffOfAssignmentPosition;
const diffOfAssignmentPosition = a.position - b.position
if (diffOfAssignmentPosition === 0) {
return 0
}
return diffOfAssignmentPosition
}
return diffOfAssignmentGroupPosition
}
return diffOfAssignmentGroupPosition;
}
};
export default assignmentHelper

View File

@ -21,20 +21,20 @@ import I18n from 'i18n!gradebook'
function hasSubmitted(submission) {
if (submission.excused) {
return true;
return true
} else if (submission.latePolicyStatus) {
return submission.latePolicyStatus !== 'missing';
return submission.latePolicyStatus !== 'missing'
}
return !!(submission.submittedAt || submission.submitted_at);
return !!(submission.submittedAt || submission.submitted_at)
}
function getSubmissionTypes(assignment) {
return (assignment.submissionTypes || assignment.submission_types);
return assignment.submissionTypes || assignment.submission_types
}
function getCourseId(assignment) {
return (assignment.courseId || assignment.course_id);
return assignment.courseId || assignment.course_id
}
const MessageStudentsWhoHelper = {
@ -51,84 +51,87 @@ import I18n from 'i18n!gradebook'
},
options(assignment) {
const options = this.allOptions();
const noSubmissions = !this.hasSubmission(assignment);
if (noSubmissions) options.splice(0, 1);
return options;
const options = this.allOptions()
const noSubmissions = !this.hasSubmission(assignment)
if (noSubmissions) options.splice(0, 1)
return options
},
allOptions() {
return [
{
text: I18n.t("Haven't submitted yet"),
subjectFn: assignment => I18n.t(
'No submission for %{assignment}',
{ assignment: assignment.name }
),
subjectFn: assignment =>
I18n.t('No submission for %{assignment}', {assignment: assignment.name}),
criteriaFn: student => !hasSubmitted(student)
},
{
text: I18n.t("Haven't been graded"),
subjectFn: assignment => I18n.t(
'No grade for %{assignment}',
{ assignment: assignment.name }
),
subjectFn: assignment =>
I18n.t('No grade for %{assignment}', {assignment: assignment.name}),
criteriaFn: student => !this.exists(student.score)
},
{
text: I18n.t('Scored less than'),
cutoff: true,
subjectFn: (assignment, cutoff) => I18n.t(
'Scored less than %{cutoff} on %{assignment}',
{ assignment: assignment.name, cutoff: I18n.n(cutoff) }
),
criteriaFn: (student, cutoff) => this.scoreWithCutoff(student, cutoff) && student.score < cutoff
subjectFn: (assignment, cutoff) =>
I18n.t('Scored less than %{cutoff} on %{assignment}', {
assignment: assignment.name,
cutoff: I18n.n(cutoff)
}),
criteriaFn: (student, cutoff) =>
this.scoreWithCutoff(student, cutoff) && student.score < cutoff
},
{
text: I18n.t('Scored more than'),
cutoff: true,
subjectFn: (assignment, cutoff) => I18n.t(
'Scored more than %{cutoff} on %{assignment}',
{ assignment: assignment.name, cutoff: I18n.n(cutoff) }
),
criteriaFn: (student, cutoff) => this.scoreWithCutoff(student, cutoff) && student.score > cutoff
subjectFn: (assignment, cutoff) =>
I18n.t('Scored more than %{cutoff} on %{assignment}', {
assignment: assignment.name,
cutoff: I18n.n(cutoff)
}),
criteriaFn: (student, cutoff) =>
this.scoreWithCutoff(student, cutoff) && student.score > cutoff
}
];
]
},
hasSubmission(assignment) {
const submissionTypes = getSubmissionTypes(assignment);
if (submissionTypes.length === 0) return false;
const submissionTypes = getSubmissionTypes(assignment)
if (submissionTypes.length === 0) return false
return _.any(submissionTypes, submissionType => submissionType !== 'none' && submissionType !== 'on_paper');
return _.any(
submissionTypes,
submissionType => submissionType !== 'none' && submissionType !== 'on_paper'
)
},
exists(value) {
return !_.isUndefined(value) && !_.isNull(value);
return !_.isUndefined(value) && !_.isNull(value)
},
scoreWithCutoff(student, cutoff) {
return this.exists(student.score)
&& student.score !== ''
&& this.exists(cutoff);
return this.exists(student.score) && student.score !== '' && this.exists(cutoff)
},
callbackFn(selected, cutoff, students) {
const criteriaFn = this.findOptionByText(selected).criteriaFn;
const studentsMatchingCriteria = _.filter(students, student => criteriaFn(student.user_data, cutoff));
return _.map(studentsMatchingCriteria, student => student.user_data.id);
const criteriaFn = this.findOptionByText(selected).criteriaFn
const studentsMatchingCriteria = _.filter(students, student =>
criteriaFn(student.user_data, cutoff)
)
return _.map(studentsMatchingCriteria, student => student.user_data.id)
},
findOptionByText(text) {
return _.find(this.allOptions(), option => option.text === text);
return _.find(this.allOptions(), option => option.text === text)
},
generateSubjectCallbackFn(assignment) {
return (selected, cutoff) => {
const cutoffString = cutoff || '';
const subjectFn = this.findOptionByText(selected).subjectFn;
return subjectFn(assignment, cutoffString);
const cutoffString = cutoff || ''
const subjectFn = this.findOptionByText(selected).subjectFn
return subjectFn(assignment, cutoffString)
}
}
}
};
export default MessageStudentsWhoHelper

View File

@ -21,25 +21,24 @@ import I18n from 'i18n!gradezilla_uploads'
import 'spin.js/jquery.spin'
export function waitForProcessing(progress) {
const dfd = $.Deferred();
const spinner = $("#spinner").spin();
const dfd = $.Deferred()
const spinner = $('#spinner').spin()
const amIDoneYet = (currentProgress) => {
if (currentProgress.workflow_state === "completed") {
$.ajaxJSON(ENV.uploaded_gradebook_data_path, "GET").then((uploadedGradebook) => {
spinner.hide();
const amIDoneYet = currentProgress => {
if (currentProgress.workflow_state === 'completed') {
$.ajaxJSON(ENV.uploaded_gradebook_data_path, 'GET').then(uploadedGradebook => {
spinner.hide()
dfd.resolve(uploadedGradebook)
});
} else if (currentProgress.workflow_state === "failed") {
dfd.reject(I18n.t("Invalid CSV file. Grades could not be updated."));
})
} else if (currentProgress.workflow_state === 'failed') {
dfd.reject(I18n.t('Invalid CSV file. Grades could not be updated.'))
} else {
setTimeout(() => {
$.ajaxJSON(`/api/v1/progress/${currentProgress.id}`, "GET")
.then(amIDoneYet);
}, 2000);
$.ajaxJSON(`/api/v1/progress/${currentProgress.id}`, 'GET').then(amIDoneYet)
}, 2000)
}
}
amIDoneYet(progress);
amIDoneYet(progress)
return dfd;
return dfd
}

View File

@ -71,7 +71,12 @@ test('hides ending info alert and removes class from iframe', () => {
})
test("doesn't show infos or add border to iframe by default", () => {
equal(el.find('.before_external_content_info_alert.screenreader-only, .after_external_content_info_alert.screenreader-only').length, 2)
equal(
el.find(
'.before_external_content_info_alert.screenreader-only, .after_external_content_info_alert.screenreader-only'
).length,
2
)
notOk(iframe.hasClass('info_alert_outline'))
})

View File

@ -16,194 +16,204 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import SubmissionStateMap from 'jsx/gradezilla/SubmissionStateMap';
import SubmissionStateMap from 'jsx/gradezilla/SubmissionStateMap'
const student = {
id: '1',
group_ids: ['1'],
sections: ['1']
};
}
function createMap(opts = {}) {
const defaults = {
hasGradingPeriods: false,
selectedGradingPeriodID: '0',
isAdmin: false
};
}
const params = Object.assign(defaults, opts);
return new SubmissionStateMap(params);
const params = Object.assign(defaults, opts)
return new SubmissionStateMap(params)
}
function createAndSetupMap(assignment, opts = {}) {
const map = createMap(opts);
const assignments = {};
assignments[assignment.id] = assignment;
map.setup([student], assignments);
return map;
const map = createMap(opts)
const assignments = {}
assignments[assignment.id] = assignment
map.setup([student], assignments)
return map
}
// TODO: the spec setup above should live in a spec helper -- at the
// time this is being written a significant amount of work is needed
// to be able to require javascript files that live in the spec directory
QUnit.module('SubmissionStateMap without grading periods');
QUnit.module('SubmissionStateMap without grading periods')
test('submission in an unpublished assignment is hidden', function() {
const assignment = { id: '1', published: false, effectiveDueDates: {} };
const map = createAndSetupMap(assignment, { hasGradingPeriods: false });
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
strictEqual(state.hideGrade, true);
});
const assignment = {id: '1', published: false, effectiveDueDates: {}}
const map = createAndSetupMap(assignment, {hasGradingPeriods: false})
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
strictEqual(state.hideGrade, true)
})
test('submission in a published assignment is not hidden', function() {
const assignment = { id: '1', published: true, effectiveDueDates: {} };
const map = createAndSetupMap(assignment, { hasGradingPeriods: false });
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
strictEqual(state.hideGrade, false);
});
const assignment = {id: '1', published: true, effectiveDueDates: {}}
const map = createAndSetupMap(assignment, {hasGradingPeriods: false})
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
strictEqual(state.hideGrade, false)
})
test('submission has grade hidden for a student without assignment visibility', function() {
const assignment = { id: '1', published: true, effectiveDueDates: {}, only_visible_to_overrides: true };
const map = createAndSetupMap(assignment, { hasGradingPeriods: false });
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
equal(state.hideGrade, true);
});
const assignment = {
id: '1',
published: true,
effectiveDueDates: {},
only_visible_to_overrides: true
}
const map = createAndSetupMap(assignment, {hasGradingPeriods: false})
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
equal(state.hideGrade, true)
})
test('submission has grade visible for a student with assignment visibility', function() {
const assignment = { id: '1', published: true, effectiveDueDates: {} };
const assignment = {id: '1', published: true, effectiveDueDates: {}}
assignment.effectiveDueDates[student.id] = {
due_at: null,
grading_period_id: null,
in_closed_grading_period: false
};
}
const map = createAndSetupMap(assignment, { hasGradingPeriods: false });
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
equal(state.hideGrade, false);
});
const map = createAndSetupMap(assignment, {hasGradingPeriods: false})
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
equal(state.hideGrade, false)
})
QUnit.module('SubmissionStateMap with grading periods and all grading periods selected', {
setup() {
this.DATE_IN_CLOSED_PERIOD = '2015-07-15';
this.DATE_NOT_IN_CLOSED_PERIOD = '2015-08-15';
this.mapOptions = { hasGradingPeriods: true, selectedGradingPeriodID: '0' };
this.DATE_IN_CLOSED_PERIOD = '2015-07-15'
this.DATE_NOT_IN_CLOSED_PERIOD = '2015-08-15'
this.mapOptions = {hasGradingPeriods: true, selectedGradingPeriodID: '0'}
}
});
})
test('submission has grade hidden for a student without assignment visibility', function() {
const assignment = { id: '1', published: true, effectiveDueDates: {}, only_visible_to_overrides: true };
const map = createAndSetupMap(assignment, this.mapOptions);
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
equal(state.hideGrade, true);
});
const assignment = {
id: '1',
published: true,
effectiveDueDates: {},
only_visible_to_overrides: true
}
const map = createAndSetupMap(assignment, this.mapOptions)
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
equal(state.hideGrade, true)
})
test('submission has grade visible for an assigned student with assignment due in a closed grading period', function() {
const assignment = { id: '1', published: true, effectiveDueDates: {} };
const assignment = {id: '1', published: true, effectiveDueDates: {}}
assignment.effectiveDueDates[student.id] = {
due_at: this.DATE_IN_CLOSED_PERIOD,
grading_period_id: '1',
in_closed_grading_period: true
};
}
const map = createAndSetupMap(assignment, this.mapOptions);
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
equal(state.hideGrade, false);
});
const map = createAndSetupMap(assignment, this.mapOptions)
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
equal(state.hideGrade, false)
})
test('submission has grade visible for an assigned student with assignment due outside of a closed grading period', function() {
const assignment = { id: '1', published: true, effectiveDueDates: {} };
const assignment = {id: '1', published: true, effectiveDueDates: {}}
assignment.effectiveDueDates[student.id] = {
due_at: this.DATE_NOT_IN_CLOSED_PERIOD,
grading_period_id: '2',
in_closed_grading_period: false
};
}
const map = createAndSetupMap(assignment, this.mapOptions);
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
equal(state.hideGrade, false);
});
const map = createAndSetupMap(assignment, this.mapOptions)
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
equal(state.hideGrade, false)
})
QUnit.module('SubmissionStateMap with grading periods and a non-closed grading period selected', {
setup() {
this.SELECTED_PERIOD_ID = '1';
this.DATE_IN_SELECTED_PERIOD = '2015-08-15';
this.DATE_NOT_IN_SELECTED_PERIOD = '2015-10-15';
this.mapOptions = { hasGradingPeriods: true, selectedGradingPeriodID: this.SELECTED_PERIOD_ID };
this.SELECTED_PERIOD_ID = '1'
this.DATE_IN_SELECTED_PERIOD = '2015-08-15'
this.DATE_NOT_IN_SELECTED_PERIOD = '2015-10-15'
this.mapOptions = {hasGradingPeriods: true, selectedGradingPeriodID: this.SELECTED_PERIOD_ID}
}
});
})
test('submission has grade hidden for a student without assignment visibility', function() {
const assignment = { id: '1', published: true, effectiveDueDates: {} };
const map = createAndSetupMap(assignment, this.mapOptions);
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
equal(state.hideGrade, true);
});
const assignment = {id: '1', published: true, effectiveDueDates: {}}
const map = createAndSetupMap(assignment, this.mapOptions)
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
equal(state.hideGrade, true)
})
test('submission has grade hidden for an assigned student with assignment due outside of the selected grading period', function() {
const assignment = { id: '1', published: true, effectiveDueDates: {} };
const assignment = {id: '1', published: true, effectiveDueDates: {}}
assignment.effectiveDueDates[student.id] = {
due_at: this.DATE_NOT_IN_SELECTED_PERIOD,
grading_period_id: '2',
in_closed_grading_period: false
};
}
const map = createAndSetupMap(assignment, this.mapOptions);
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
equal(state.hideGrade, true);
});
const map = createAndSetupMap(assignment, this.mapOptions)
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
equal(state.hideGrade, true)
})
test('submission has grade visible for an assigned student with assignment due in the selected grading period', function() {
const assignment = { id: '1', published: true, effectiveDueDates: {} };
const assignment = {id: '1', published: true, effectiveDueDates: {}}
assignment.effectiveDueDates[student.id] = {
due_at: this.DATE_IN_SELECTED_PERIOD,
grading_period_id: this.SELECTED_PERIOD_ID,
in_closed_grading_period: false
};
}
const map = createAndSetupMap(assignment, this.mapOptions);
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
equal(state.hideGrade, false);
});
const map = createAndSetupMap(assignment, this.mapOptions)
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
equal(state.hideGrade, false)
})
QUnit.module('SubmissionStateMap with grading periods and a closed grading period selected', {
setup() {
this.SELECTED_PERIOD_ID = '1';
this.DATE_IN_SELECTED_PERIOD = '2015-07-15';
this.DATE_NOT_IN_SELECTED_PERIOD = '2015-08-15';
this.mapOptions = { hasGradingPeriods: true, selectedGradingPeriodID: this.SELECTED_PERIOD_ID };
this.SELECTED_PERIOD_ID = '1'
this.DATE_IN_SELECTED_PERIOD = '2015-07-15'
this.DATE_NOT_IN_SELECTED_PERIOD = '2015-08-15'
this.mapOptions = {hasGradingPeriods: true, selectedGradingPeriodID: this.SELECTED_PERIOD_ID}
}
});
})
test('submission has grade hidden for a student without assignment visibility', function() {
const assignment = { id: '1', published: true, effectiveDueDates: {} };
const map = createAndSetupMap(assignment, this.mapOptions);
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
equal(state.hideGrade, true);
});
const assignment = {id: '1', published: true, effectiveDueDates: {}}
const map = createAndSetupMap(assignment, this.mapOptions)
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
equal(state.hideGrade, true)
})
test('submission has grade hidden for an assigned student with assignment due outside of the selected grading period', function() {
const assignment = { id: '1', published: true, effectiveDueDates: {} };
const assignment = {id: '1', published: true, effectiveDueDates: {}}
assignment.effectiveDueDates[student.id] = {
due_at: this.DATE_NOT_IN_SELECTED_PERIOD,
grading_period_id: '2',
in_closed_grading_period: false
};
}
const map = createAndSetupMap(assignment, this.mapOptions);
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
equal(state.hideGrade, true);
});
const map = createAndSetupMap(assignment, this.mapOptions)
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
equal(state.hideGrade, true)
})
test('submission has grade visible for an assigned student with assignment due in the selected grading period', function() {
const assignment = { id: '1', published: true, effectiveDueDates: {} };
const assignment = {id: '1', published: true, effectiveDueDates: {}}
assignment.effectiveDueDates[student.id] = {
due_at: this.DATE_IN_SELECTED_PERIOD,
grading_period_id: this.SELECTED_PERIOD_ID,
in_closed_grading_period: true
};
}
const map = createAndSetupMap(assignment, this.mapOptions);
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
equal(state.hideGrade, false);
});
const map = createAndSetupMap(assignment, this.mapOptions)
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
equal(state.hideGrade, false)
})

View File

@ -16,13 +16,13 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import SubmissionStateMap from 'jsx/gradezilla/SubmissionStateMap';
import SubmissionStateMap from 'jsx/gradezilla/SubmissionStateMap'
const student = {
id: '1',
group_ids: ['1'],
sections: ['1']
};
}
function createMap(opts = {}) {
const params = {
@ -30,29 +30,29 @@ function createMap (opts = {}) {
selectedGradingPeriodID: '0',
isAdmin: false,
...opts
};
}
return new SubmissionStateMap(params);
return new SubmissionStateMap(params)
}
function createAndSetupMap(assignment, opts = {}) {
const submissionStateMap = createMap(opts);
const assignments = {};
assignments[assignment.id] = assignment;
submissionStateMap.setup([student], assignments);
return submissionStateMap;
const submissionStateMap = createMap(opts)
const assignments = {}
assignments[assignment.id] = assignment
submissionStateMap.setup([student], assignments)
return submissionStateMap
}
QUnit.module('SubmissionStateMap without grading periods', function(suiteHooks) {
const dueDate = '2015-07-15';
let assignment;
let submissionStateMap;
let options;
const dueDate = '2015-07-15'
let assignment
let submissionStateMap
let options
suiteHooks.beforeEach(() => {
options = { hasGradingPeriods: false };
assignment = { id: '1', published: true, effectiveDueDates: {} };
});
options = {hasGradingPeriods: false}
assignment = {id: '1', published: true, effectiveDueDates: {}}
})
QUnit.module('inNoGradingPeriod', function(_hooks) {
test('returns undefined if submission has no grading period', function() {
@ -60,12 +60,15 @@ QUnit.module('SubmissionStateMap without grading periods', function (suiteHooks)
due_at: dueDate,
in_closed_grading_period: false
}
submissionStateMap = createAndSetupMap(assignment, options);
submissionStateMap = createAndSetupMap(assignment, options)
const state = submissionStateMap.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
const state = submissionStateMap.getSubmissionState({
user_id: student.id,
assignment_id: assignment.id
})
strictEqual(state.inNoGradingPeriod, undefined);
});
strictEqual(state.inNoGradingPeriod, undefined)
})
test('returns undefined if submission has a grading period', function() {
assignment.effectiveDueDates[student.id] = {
@ -73,86 +76,104 @@ QUnit.module('SubmissionStateMap without grading periods', function (suiteHooks)
grading_period_id: 1,
in_closed_grading_period: false
}
submissionStateMap = createAndSetupMap(assignment, options);
submissionStateMap = createAndSetupMap(assignment, options)
const state = submissionStateMap.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
const state = submissionStateMap.getSubmissionState({
user_id: student.id,
assignment_id: assignment.id
})
strictEqual(state.inNoGradingPeriod, undefined);
});
});
strictEqual(state.inNoGradingPeriod, undefined)
})
})
QUnit.module('inOtherGradingPeriod', function(hooks) {
hooks.beforeEach(() => {
assignment.effectiveDueDates[student.id] = {
due_at: dueDate,
in_closed_grading_period: false
};
});
}
})
test('returns undefined if filtering by grading period and submission is not in any grading period', function() {
submissionStateMap = createAndSetupMap(assignment, options);
submissionStateMap = createAndSetupMap(assignment, options)
const state = submissionStateMap.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
const state = submissionStateMap.getSubmissionState({
user_id: student.id,
assignment_id: assignment.id
})
strictEqual(state.inOtherGradingPeriod, undefined);
});
strictEqual(state.inOtherGradingPeriod, undefined)
})
test('returns undefined if filtering by grading period and submission is in another grading period', function() {
assignment.effectiveDueDates[student.id].grading_period_id = '1';
submissionStateMap = createAndSetupMap(assignment, options);
assignment.effectiveDueDates[student.id].grading_period_id = '1'
submissionStateMap = createAndSetupMap(assignment, options)
const state = submissionStateMap.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
const state = submissionStateMap.getSubmissionState({
user_id: student.id,
assignment_id: assignment.id
})
strictEqual(state.inOtherGradingPeriod, undefined);
});
strictEqual(state.inOtherGradingPeriod, undefined)
})
test('returns undefined if filtering by grading period and submission is in the same grading period', function() {
assignment.effectiveDueDates[student.id].grading_period_id = '2';
submissionStateMap = createAndSetupMap(assignment, options);
assignment.effectiveDueDates[student.id].grading_period_id = '2'
submissionStateMap = createAndSetupMap(assignment, options)
const state = submissionStateMap.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
const state = submissionStateMap.getSubmissionState({
user_id: student.id,
assignment_id: assignment.id
})
strictEqual(state.inOtherGradingPeriod, undefined);
});
});
strictEqual(state.inOtherGradingPeriod, undefined)
})
})
QUnit.module('inClosedGradingPeriod', function(hooks) {
hooks.beforeEach(() => {
assignment.effectiveDueDates[student.id] = {
due_at: dueDate,
};
});
due_at: dueDate
}
})
test('returns undefined if submission is in a closed grading period', function() {
assignment.effectiveDueDates[student.id].in_closed_grading_period = true;
submissionStateMap = createAndSetupMap(assignment, options);
assignment.effectiveDueDates[student.id].in_closed_grading_period = true
submissionStateMap = createAndSetupMap(assignment, options)
const state = submissionStateMap.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
const state = submissionStateMap.getSubmissionState({
user_id: student.id,
assignment_id: assignment.id
})
strictEqual(state.inClosedGradingPeriod, undefined);
});
strictEqual(state.inClosedGradingPeriod, undefined)
})
test('returns undefined if submission is in a closed grading period', function() {
assignment.effectiveDueDates[student.id].in_closed_grading_period = false;
submissionStateMap = createAndSetupMap(assignment, options);
assignment.effectiveDueDates[student.id].in_closed_grading_period = false
submissionStateMap = createAndSetupMap(assignment, options)
const state = submissionStateMap.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
const state = submissionStateMap.getSubmissionState({
user_id: student.id,
assignment_id: assignment.id
})
strictEqual(state.inClosedGradingPeriod, undefined);
});
});
});
strictEqual(state.inClosedGradingPeriod, undefined)
})
})
})
QUnit.module('SubmissionStateMap with grading periods', function(suiteHooks) {
const dueDate = '2015-07-15';
let assignment;
let submissionStateMap;
let options;
const dueDate = '2015-07-15'
let assignment
let submissionStateMap
let options
suiteHooks.beforeEach(() => {
options = { hasGradingPeriods: true, selectedGradingPeriodID: '0' };
assignment = { id: '1', published: true, effectiveDueDates: {} };
});
options = {hasGradingPeriods: true, selectedGradingPeriodID: '0'}
assignment = {id: '1', published: true, effectiveDueDates: {}}
})
QUnit.module('inNoGradingPeriod', function(_hooks2) {
test('returns true if submission has no grading period', function() {
@ -160,12 +181,15 @@ QUnit.module('SubmissionStateMap with grading periods', function (suiteHooks) {
due_at: dueDate,
in_closed_grading_period: false
}
submissionStateMap = createAndSetupMap(assignment, options);
submissionStateMap = createAndSetupMap(assignment, options)
const state = submissionStateMap.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
const state = submissionStateMap.getSubmissionState({
user_id: student.id,
assignment_id: assignment.id
})
strictEqual(state.inNoGradingPeriod, true);
});
strictEqual(state.inNoGradingPeriod, true)
})
test('returns false if submission has a grading period', function() {
assignment.effectiveDueDates[student.id] = {
@ -173,74 +197,92 @@ QUnit.module('SubmissionStateMap with grading periods', function (suiteHooks) {
grading_period_id: 1,
in_closed_grading_period: false
}
submissionStateMap = createAndSetupMap(assignment, options);
submissionStateMap = createAndSetupMap(assignment, options)
const state = submissionStateMap.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
const state = submissionStateMap.getSubmissionState({
user_id: student.id,
assignment_id: assignment.id
})
strictEqual(state.inNoGradingPeriod, false);
});
});
strictEqual(state.inNoGradingPeriod, false)
})
})
QUnit.module('inOtherGradingPeriod', function(hooks) {
hooks.beforeEach(() => {
options = { hasGradingPeriods: true, selectedGradingPeriodID: '2' };
options = {hasGradingPeriods: true, selectedGradingPeriodID: '2'}
assignment.effectiveDueDates[student.id] = {
due_at: dueDate,
in_closed_grading_period: false
};
});
}
})
test('returns false if filtering by grading period and submission is not in any grading period', function() {
submissionStateMap = createAndSetupMap(assignment, options);
submissionStateMap = createAndSetupMap(assignment, options)
const state = submissionStateMap.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
const state = submissionStateMap.getSubmissionState({
user_id: student.id,
assignment_id: assignment.id
})
strictEqual(state.inOtherGradingPeriod, false);
});
strictEqual(state.inOtherGradingPeriod, false)
})
test('returns true if filtering by grading period and submission is in another grading period', function() {
assignment.effectiveDueDates[student.id].grading_period_id = '1';
submissionStateMap = createAndSetupMap(assignment, options);
assignment.effectiveDueDates[student.id].grading_period_id = '1'
submissionStateMap = createAndSetupMap(assignment, options)
const state = submissionStateMap.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
const state = submissionStateMap.getSubmissionState({
user_id: student.id,
assignment_id: assignment.id
})
strictEqual(state.inOtherGradingPeriod, true);
});
strictEqual(state.inOtherGradingPeriod, true)
})
test('returns false if filtering by grading period and submission is in the same grading period', function() {
assignment.effectiveDueDates[student.id].grading_period_id = '2';
submissionStateMap = createAndSetupMap(assignment, options);
assignment.effectiveDueDates[student.id].grading_period_id = '2'
submissionStateMap = createAndSetupMap(assignment, options)
const state = submissionStateMap.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
const state = submissionStateMap.getSubmissionState({
user_id: student.id,
assignment_id: assignment.id
})
strictEqual(state.inOtherGradingPeriod, false);
});
});
strictEqual(state.inOtherGradingPeriod, false)
})
})
QUnit.module('inClosedGradingPeriod', function(hooks) {
hooks.beforeEach(() => {
options = { hasGradingPeriods: true, selectedGradingPeriodID: '2' };
options = {hasGradingPeriods: true, selectedGradingPeriodID: '2'}
assignment.effectiveDueDates[student.id] = {
due_at: dueDate,
};
});
due_at: dueDate
}
})
test('returns true if submission is in a closed grading period', function() {
assignment.effectiveDueDates[student.id].in_closed_grading_period = true;
submissionStateMap = createAndSetupMap(assignment, options);
assignment.effectiveDueDates[student.id].in_closed_grading_period = true
submissionStateMap = createAndSetupMap(assignment, options)
const state = submissionStateMap.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
const state = submissionStateMap.getSubmissionState({
user_id: student.id,
assignment_id: assignment.id
})
strictEqual(state.inClosedGradingPeriod, true);
});
strictEqual(state.inClosedGradingPeriod, true)
})
test('returns true if submission is in a closed grading period', function() {
assignment.effectiveDueDates[student.id].in_closed_grading_period = false;
submissionStateMap = createAndSetupMap(assignment, options);
assignment.effectiveDueDates[student.id].in_closed_grading_period = false
submissionStateMap = createAndSetupMap(assignment, options)
const state = submissionStateMap.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
const state = submissionStateMap.getSubmissionState({
user_id: student.id,
assignment_id: assignment.id
})
strictEqual(state.inClosedGradingPeriod, false);
});
});
});
strictEqual(state.inClosedGradingPeriod, false)
})
})
})

View File

@ -16,208 +16,218 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import SubmissionStateMap from 'jsx/gradezilla/SubmissionStateMap';
import SubmissionStateMap from 'jsx/gradezilla/SubmissionStateMap'
const student = {
id: '1',
group_ids: ['1'],
sections: ['1']
};
}
function createMap(opts = {}) {
const defaults = {
hasGradingPeriods: false,
selectedGradingPeriodID: '0',
isAdmin: false
};
}
const params = { ...defaults, ...opts };
return new SubmissionStateMap(params);
const params = {...defaults, ...opts}
return new SubmissionStateMap(params)
}
function createAndSetupMap(assignment, opts = {}) {
const map = createMap(opts);
const assignments = {};
assignments[assignment.id] = assignment;
map.setup([student], assignments);
return map;
const map = createMap(opts)
const assignments = {}
assignments[assignment.id] = assignment
map.setup([student], assignments)
return map
}
// TODO: the spec setup above should live in a spec helper -- at the
// time this is being written a significant amount of work is needed
// to be able to require javascript files that live in the spec directory
QUnit.module('SubmissionStateMap without grading periods');
QUnit.module('SubmissionStateMap without grading periods')
test('submission in an unpublished assignment is locked', function() {
const assignment = { id: '1', published: false, effectiveDueDates: {} };
const map = createAndSetupMap(assignment, { hasGradingPeriods: false });
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
strictEqual(state.locked, true);
});
const assignment = {id: '1', published: false, effectiveDueDates: {}}
const map = createAndSetupMap(assignment, {hasGradingPeriods: false})
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
strictEqual(state.locked, true)
})
test('submission in a published assignment is not locked', function() {
const assignment = { id: '1', published: true, effectiveDueDates: {} };
const map = createAndSetupMap(assignment, { hasGradingPeriods: false });
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
strictEqual(state.locked, false);
});
const assignment = {id: '1', published: true, effectiveDueDates: {}}
const map = createAndSetupMap(assignment, {hasGradingPeriods: false})
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
strictEqual(state.locked, false)
})
test('submission is locked for a student without assignment visibility', function() {
const assignment = { id: '1', published: true, effectiveDueDates: {}, only_visible_to_overrides: true };
const map = createAndSetupMap(assignment, { hasGradingPeriods: false });
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
equal(state.locked, true);
});
const assignment = {
id: '1',
published: true,
effectiveDueDates: {},
only_visible_to_overrides: true
}
const map = createAndSetupMap(assignment, {hasGradingPeriods: false})
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
equal(state.locked, true)
})
test('submission is unlocked for an assigned student', function() {
const assignment = { id: '1', published: true, effectiveDueDates: {} };
const assignment = {id: '1', published: true, effectiveDueDates: {}}
assignment.effectiveDueDates[student.id] = {
due_at: null,
grading_period_id: null,
in_closed_grading_period: false
};
}
const map = createAndSetupMap(assignment, { hasGradingPeriods: false });
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
equal(state.locked, false);
});
const map = createAndSetupMap(assignment, {hasGradingPeriods: false})
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
equal(state.locked, false)
})
QUnit.module('SubmissionStateMap with grading periods and all grading periods selected', {
setup() {
this.DATE_IN_CLOSED_PERIOD = '2015-07-15';
this.DATE_NOT_IN_CLOSED_PERIOD = '2015-08-15';
this.mapOptions = { hasGradingPeriods: true, selectedGradingPeriodID: '0' };
this.DATE_IN_CLOSED_PERIOD = '2015-07-15'
this.DATE_NOT_IN_CLOSED_PERIOD = '2015-08-15'
this.mapOptions = {hasGradingPeriods: true, selectedGradingPeriodID: '0'}
}
});
})
test('submission is locked for a student without assignment visibility', function() {
const assignment = { id: '1', published: true, effectiveDueDates: {}, only_visible_to_overrides: true };
const map = createAndSetupMap(assignment, this.mapOptions);
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
equal(state.locked, true);
});
const assignment = {
id: '1',
published: true,
effectiveDueDates: {},
only_visible_to_overrides: true
}
const map = createAndSetupMap(assignment, this.mapOptions)
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
equal(state.locked, true)
})
test('submission is locked for an assigned student with assignment due in a closed grading period', function() {
const assignment = { id: '1', published: true, effectiveDueDates: {} };
const assignment = {id: '1', published: true, effectiveDueDates: {}}
assignment.effectiveDueDates[student.id] = {
due_at: this.DATE_IN_CLOSED_PERIOD,
grading_period_id: '1',
in_closed_grading_period: true
};
}
const map = createAndSetupMap(assignment, this.mapOptions);
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
equal(state.locked, true);
});
const map = createAndSetupMap(assignment, this.mapOptions)
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
equal(state.locked, true)
})
test('user is admin: submission is unlocked for an assigned student with assignment due in a closed grading period', function() {
const assignment = { id: '1', published: true, effectiveDueDates: {} };
const assignment = {id: '1', published: true, effectiveDueDates: {}}
assignment.effectiveDueDates[student.id] = {
due_at: this.DATE_IN_CLOSED_PERIOD,
grading_period_id: '1',
in_closed_grading_period: true
};
}
const mapOptions = { ...this.mapOptions, isAdmin: true };
const map = createAndSetupMap(assignment, mapOptions);
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
equal(state.locked, false);
});
const mapOptions = {...this.mapOptions, isAdmin: true}
const map = createAndSetupMap(assignment, mapOptions)
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
equal(state.locked, false)
})
test('submission is unlocked for an assigned student with assignment due outside of a closed grading period', function() {
const assignment = { id: '1', published: true, effectiveDueDates: {} };
const assignment = {id: '1', published: true, effectiveDueDates: {}}
assignment.effectiveDueDates[student.id] = {
due_at: this.DATE_NOT_IN_CLOSED_PERIOD,
grading_period_id: '1',
in_closed_grading_period: false
};
}
const map = createAndSetupMap(assignment, this.mapOptions);
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
equal(state.locked, false);
});
const map = createAndSetupMap(assignment, this.mapOptions)
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
equal(state.locked, false)
})
QUnit.module('SubmissionStateMap with grading periods and a non-closed grading period selected', {
setup() {
this.DATE_IN_SELECTED_PERIOD = '2015-07-15';
this.DATE_NOT_IN_SELECTED_PERIOD = '2015-08-15';
this.SELECTED_PERIOD_ID = '1';
this.mapOptions = { hasGradingPeriods: true, selectedGradingPeriodID: this.SELECTED_PERIOD_ID };
this.DATE_IN_SELECTED_PERIOD = '2015-07-15'
this.DATE_NOT_IN_SELECTED_PERIOD = '2015-08-15'
this.SELECTED_PERIOD_ID = '1'
this.mapOptions = {hasGradingPeriods: true, selectedGradingPeriodID: this.SELECTED_PERIOD_ID}
}
});
})
test('submission is locked for an assigned student with assignment due outside of the selected grading period', function() {
const assignment = { id: '1', published: true, effectiveDueDates: {} };
const assignment = {id: '1', published: true, effectiveDueDates: {}}
assignment.effectiveDueDates[student.id] = {
due_at: this.DATE_NOT_IN_SELECTED_PERIOD,
grading_period_id: '2',
in_closed_grading_period: false
};
}
const map = createAndSetupMap(assignment, this.mapOptions);
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
equal(state.locked, true);
});
const map = createAndSetupMap(assignment, this.mapOptions)
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
equal(state.locked, true)
})
test('submission is unlocked for an assigned student with assignment due in the selected grading period', function() {
const assignment = { id: '1', published: true, effectiveDueDates: {} };
const assignment = {id: '1', published: true, effectiveDueDates: {}}
assignment.effectiveDueDates[student.id] = {
due_at: this.DATE_IN_SELECTED_PERIOD,
grading_period_id: this.SELECTED_PERIOD_ID,
in_closed_grading_period: false
};
}
const map = createAndSetupMap(assignment, this.mapOptions);
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
equal(state.locked, false);
});
const map = createAndSetupMap(assignment, this.mapOptions)
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
equal(state.locked, false)
})
QUnit.module('SubmissionStateMap with grading periods and a closed grading period selected', {
setup() {
this.DATE_IN_SELECTED_PERIOD = '2015-07-15';
this.DATE_NOT_IN_SELECTED_PERIOD = '2015-08-15';
this.SELECTED_PERIOD_ID = '1';
this.mapOptions = { hasGradingPeriods: true, selectedGradingPeriodID: this.SELECTED_PERIOD_ID };
this.DATE_IN_SELECTED_PERIOD = '2015-07-15'
this.DATE_NOT_IN_SELECTED_PERIOD = '2015-08-15'
this.SELECTED_PERIOD_ID = '1'
this.mapOptions = {hasGradingPeriods: true, selectedGradingPeriodID: this.SELECTED_PERIOD_ID}
}
});
})
test('submission is locked for an assigned student with assignment due outside of the selected grading period', function() {
const assignment = { id: '1', published: true, effectiveDueDates: {} };
const assignment = {id: '1', published: true, effectiveDueDates: {}}
assignment.effectiveDueDates[student.id] = {
due_at: this.DATE_NOT_IN_SELECTED_PERIOD,
grading_period_id: '2',
in_closed_grading_period: false
};
}
const map = createAndSetupMap(assignment, this.mapOptions);
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
equal(state.locked, true);
});
const map = createAndSetupMap(assignment, this.mapOptions)
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
equal(state.locked, true)
})
test('submission is locked for an assigned student with assignment due in the selected grading period', function() {
const assignment = { id: '1', published: true, effectiveDueDates: {} };
const assignment = {id: '1', published: true, effectiveDueDates: {}}
assignment.effectiveDueDates[student.id] = {
due_at: this.DATE_IN_SELECTED_PERIOD,
grading_period_id: this.SELECTED_PERIOD_ID,
in_closed_grading_period: true
};
}
const map = createAndSetupMap(assignment, this.mapOptions);
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
equal(state.locked, true);
});
const map = createAndSetupMap(assignment, this.mapOptions)
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
equal(state.locked, true)
})
test('user is admin: submission is unlocked for an assigned student with assignment due in the selected grading period', function() {
const assignment = { id: '1', published: true, effectiveDueDates: {} };
const assignment = {id: '1', published: true, effectiveDueDates: {}}
assignment.effectiveDueDates[student.id] = {
due_at: this.DATE_IN_SELECTED_PERIOD,
grading_period_id: this.SELECTED_PERIOD_ID,
in_closed_grading_period: true
};
}
const mapOptions = { ...this.mapOptions, isAdmin: true };
const map = createAndSetupMap(assignment, mapOptions);
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
equal(state.locked, false);
});
const mapOptions = {...this.mapOptions, isAdmin: true}
const map = createAndSetupMap(assignment, mapOptions)
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
equal(state.locked, false)
})

View File

@ -16,30 +16,32 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import {fromJS} from 'immutable';
import moment from 'moment';
import SubmissionStateMap from 'jsx/gradezilla/SubmissionStateMap';
import {fromJS} from 'immutable'
import moment from 'moment'
import SubmissionStateMap from 'jsx/gradezilla/SubmissionStateMap'
const studentWithoutSubmission = {
id: '1',
group_ids: ['1'],
sections: ['1']
};
}
const studentWithSubmission = {
id: '1',
group_ids: ['1'],
sections: ['1'],
assignment_1: {}
};
}
const yesterday = moment(new Date()).subtract(1, 'day');
const tomorrow = moment(new Date()).add(1, 'day');
const yesterday = moment(new Date()).subtract(1, 'day')
const tomorrow = moment(new Date()).add(1, 'day')
const baseAssignment = fromJS({
id: '1',
published: true,
effectiveDueDates: {1: {due_at: new Date(), grading_period_id: '2', in_closed_grading_period: true}}
effectiveDueDates: {
1: {due_at: new Date(), grading_period_id: '2', in_closed_grading_period: true}
}
})
const unpublishedAssignment = baseAssignment.merge({published: false})
const anonymousMutedAssignment = baseAssignment.merge({
@ -47,10 +49,14 @@ const anonymousMutedAssignment = baseAssignment.merge({
anonymous_grading: true,
muted: true
})
const moderatedAndGradesUnpublishedAssignment =
baseAssignment.merge({moderated_grading: true, grades_published: false})
const hiddenFromStudent =
baseAssignment.merge({only_visible_to_overrides: true, assignment_visibility: []})
const moderatedAndGradesUnpublishedAssignment = baseAssignment.merge({
moderated_grading: true,
grades_published: false
})
const hiddenFromStudent = baseAssignment.merge({
only_visible_to_overrides: true,
assignment_visibility: []
})
const hasGradingPeriodsAssignment = baseAssignment
function createMap(opts = {}) {
@ -58,18 +64,18 @@ function createMap (opts = {}) {
hasGradingPeriods: false,
selectedGradingPeriodID: '0',
isAdmin: false
};
}
const params = { ...defaults, ...opts };
return new SubmissionStateMap(params);
const params = {...defaults, ...opts}
return new SubmissionStateMap(params)
}
function createAndSetupMap(assignment, student, opts = {}) {
const map = createMap(opts);
const assignments = {};
assignments[assignment.id] = assignment;
map.setup([student], assignments);
return map;
const map = createMap(opts)
const assignments = {}
assignments[assignment.id] = assignment
map.setup([student], assignments)
return map
}
QUnit.module('#setSubmissionCellState', function() {
@ -77,21 +83,27 @@ QUnit.module('#setSubmissionCellState', function() {
const assignment = {
id: '1',
published: false
};
const map = createAndSetupMap(assignment, studentWithSubmission);
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
strictEqual(submission.locked, true);
});
}
const map = createAndSetupMap(assignment, studentWithSubmission)
const submission = map.getSubmissionState({
user_id: studentWithSubmission.id,
assignment_id: assignment.id
})
strictEqual(submission.locked, true)
})
test('the submission state has hideGrade set if assignment is not published', function() {
const assignment = {
id: '1',
published: false
};
const map = createAndSetupMap(assignment, studentWithSubmission);
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
strictEqual(submission.hideGrade, true);
});
}
const map = createAndSetupMap(assignment, studentWithSubmission)
const submission = map.getSubmissionState({
user_id: studentWithSubmission.id,
assignment_id: assignment.id
})
strictEqual(submission.hideGrade, true)
})
test('the submission state is locked if assignment is not visible', function() {
const assignment = {
@ -99,11 +111,14 @@ QUnit.module('#setSubmissionCellState', function() {
published: true,
only_visible_to_overrides: true,
assignment_visibility: []
};
const map = createAndSetupMap(assignment, studentWithSubmission);
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
strictEqual(submission.locked, true);
});
}
const map = createAndSetupMap(assignment, studentWithSubmission)
const submission = map.getSubmissionState({
user_id: studentWithSubmission.id,
assignment_id: assignment.id
})
strictEqual(submission.locked, true)
})
test('the submission state has hideGrade set if assignment is not visible', function() {
const assignment = {
@ -111,33 +126,42 @@ QUnit.module('#setSubmissionCellState', function() {
published: true,
only_visible_to_overrides: true,
assignment_visibility: []
};
const map = createAndSetupMap(assignment, studentWithSubmission);
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
strictEqual(submission.hideGrade, true);
});
}
const map = createAndSetupMap(assignment, studentWithSubmission)
const submission = map.getSubmissionState({
user_id: studentWithSubmission.id,
assignment_id: assignment.id
})
strictEqual(submission.hideGrade, true)
})
test('the submission state is not locked if assignment is published and visible', function() {
const assignment = {
id: '1',
published: true,
only_visible_to_overrides: false
};
const map = createAndSetupMap(assignment, studentWithSubmission);
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
strictEqual(submission.locked, false);
});
}
const map = createAndSetupMap(assignment, studentWithSubmission)
const submission = map.getSubmissionState({
user_id: studentWithSubmission.id,
assignment_id: assignment.id
})
strictEqual(submission.locked, false)
})
test('the submission state has hideGrade not set if assignment is published and visible', function() {
const assignment = {
id: '1',
published: true,
only_visible_to_overrides: false
};
const map = createAndSetupMap(assignment, studentWithSubmission);
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
strictEqual(submission.hideGrade, false);
});
}
const map = createAndSetupMap(assignment, studentWithSubmission)
const submission = map.getSubmissionState({
user_id: studentWithSubmission.id,
assignment_id: assignment.id
})
strictEqual(submission.hideGrade, false)
})
test('the submission state is locked when the student is not assigned', function() {
const assignment = {
@ -147,7 +171,10 @@ QUnit.module('#setSubmissionCellState', function() {
assignment_visibility: ['2']
}
const map = createAndSetupMap(assignment, studentWithSubmission)
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id })
const submission = map.getSubmissionState({
user_id: studentWithSubmission.id,
assignment_id: assignment.id
})
strictEqual(submission.locked, true)
})
@ -156,22 +183,28 @@ QUnit.module('#setSubmissionCellState', function() {
id: '1',
published: true,
moderated_grading: false
};
const map = createAndSetupMap(assignment, studentWithSubmission);
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
strictEqual(submission.locked, false);
});
}
const map = createAndSetupMap(assignment, studentWithSubmission)
const submission = map.getSubmissionState({
user_id: studentWithSubmission.id,
assignment_id: assignment.id
})
strictEqual(submission.locked, false)
})
test('the submission state has hideGrade not set if not moderated grading', function() {
const assignment = {
id: '1',
published: true,
moderated_grading: false
};
const map = createAndSetupMap(assignment, studentWithSubmission);
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
strictEqual(submission.hideGrade, false);
});
}
const map = createAndSetupMap(assignment, studentWithSubmission)
const submission = map.getSubmissionState({
user_id: studentWithSubmission.id,
assignment_id: assignment.id
})
strictEqual(submission.hideGrade, false)
})
test('the submission state is not locked if moderated grading and grades published', function() {
const assignment = {
@ -179,11 +212,14 @@ QUnit.module('#setSubmissionCellState', function() {
published: true,
moderated_grading: true,
grades_published: true
};
const map = createAndSetupMap(assignment, studentWithSubmission);
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
strictEqual(submission.locked, false);
});
}
const map = createAndSetupMap(assignment, studentWithSubmission)
const submission = map.getSubmissionState({
user_id: studentWithSubmission.id,
assignment_id: assignment.id
})
strictEqual(submission.locked, false)
})
test('the submission state has hideGrade not set if moderated grading and grades published', function() {
const assignment = {
@ -191,11 +227,14 @@ QUnit.module('#setSubmissionCellState', function() {
published: true,
moderated_grading: true,
grades_published: true
};
const map = createAndSetupMap(assignment, studentWithSubmission);
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
strictEqual(submission.hideGrade, false);
});
}
const map = createAndSetupMap(assignment, studentWithSubmission)
const submission = map.getSubmissionState({
user_id: studentWithSubmission.id,
assignment_id: assignment.id
})
strictEqual(submission.hideGrade, false)
})
test('the submission state is locked if moderated grading and grades not published', function() {
const assignment = {
@ -203,11 +242,14 @@ QUnit.module('#setSubmissionCellState', function() {
published: true,
moderated_grading: true,
grades_published: false
};
const map = createAndSetupMap(assignment, studentWithSubmission);
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
strictEqual(submission.locked, true);
});
}
const map = createAndSetupMap(assignment, studentWithSubmission)
const submission = map.getSubmissionState({
user_id: studentWithSubmission.id,
assignment_id: assignment.id
})
strictEqual(submission.locked, true)
})
test('the submission state has hideGrade not set if moderated grading and grades not published', function() {
const assignment = {
@ -215,11 +257,14 @@ QUnit.module('#setSubmissionCellState', function() {
published: true,
moderated_grading: true,
grades_published: false
};
const map = createAndSetupMap(assignment, studentWithSubmission);
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
strictEqual(submission.hideGrade, false);
});
}
const map = createAndSetupMap(assignment, studentWithSubmission)
const submission = map.getSubmissionState({
user_id: studentWithSubmission.id,
assignment_id: assignment.id
})
strictEqual(submission.hideGrade, false)
})
QUnit.module('when the assignment is anonymous', function(hooks) {
let assignment
@ -231,26 +276,38 @@ QUnit.module('#setSubmissionCellState', function() {
test('the submission state is locked when anonymize_students is true', function() {
assignment.anonymize_students = true
const map = createAndSetupMap(assignment, studentWithSubmission)
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id })
const submission = map.getSubmissionState({
user_id: studentWithSubmission.id,
assignment_id: assignment.id
})
strictEqual(submission.locked, true)
})
test('the submission state is hidden when anonymize_students is true', function() {
assignment.anonymize_students = true
const map = createAndSetupMap(assignment, studentWithSubmission)
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id })
const submission = map.getSubmissionState({
user_id: studentWithSubmission.id,
assignment_id: assignment.id
})
strictEqual(submission.hideGrade, true)
})
test('the submission state is unlocked when the assignment is unmuted', function() {
const map = createAndSetupMap(assignment, studentWithSubmission)
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id })
const submission = map.getSubmissionState({
user_id: studentWithSubmission.id,
assignment_id: assignment.id
})
strictEqual(submission.locked, false)
})
test('the submission state is not hidden when the assignment is unmuted', function() {
const map = createAndSetupMap(assignment, studentWithSubmission)
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id })
const submission = map.getSubmissionState({
user_id: studentWithSubmission.id,
assignment_id: assignment.id
})
strictEqual(submission.hideGrade, false)
})
})
@ -261,68 +318,71 @@ QUnit.module('#setSubmissionCellState', function() {
id: '1',
published: true,
effectiveDueDates: {1: {due_at: yesterday}}
};
const map = createAndSetupMap(assignment, studentWithoutSubmission);
const submission = map.getSubmission(studentWithoutSubmission.id, assignment.id);
strictEqual(submission.missing, true);
});
}
const map = createAndSetupMap(assignment, studentWithoutSubmission)
const submission = map.getSubmission(studentWithoutSubmission.id, assignment.id)
strictEqual(submission.missing, true)
})
test('the submission object is not missing if the assignment is not late', function() {
const assignment = {
id: '1',
published: true,
effectiveDueDates: {1: {due_at: tomorrow}}
};
const map = createAndSetupMap(assignment, studentWithoutSubmission);
const submission = map.getSubmission(studentWithoutSubmission.id, assignment.id);
strictEqual(submission.missing, false);
});
}
const map = createAndSetupMap(assignment, studentWithoutSubmission)
const submission = map.getSubmission(studentWithoutSubmission.id, assignment.id)
strictEqual(submission.missing, false)
})
test('the submission object is not missing, if the assignment is not late ' +
'and there are no due dates', function () {
test(
'the submission object is not missing, if the assignment is not late ' +
'and there are no due dates',
function() {
const assignment = {
id: '1',
published: true,
effectiveDueDates: {}
};
const map = createAndSetupMap(assignment, studentWithoutSubmission);
const submission = map.getSubmission(studentWithoutSubmission.id, assignment.id);
strictEqual(submission.missing, false);
});
}
const map = createAndSetupMap(assignment, studentWithoutSubmission)
const submission = map.getSubmission(studentWithoutSubmission.id, assignment.id)
strictEqual(submission.missing, false)
}
)
test('the submission object has seconds_late set to zero', function() {
const assignment = {
id: '1',
published: true,
effectiveDueDates: {1: {due_at: new Date()}}
};
const map = createAndSetupMap(assignment, studentWithoutSubmission);
const submission = map.getSubmission(studentWithoutSubmission.id, assignment.id);
strictEqual(submission.seconds_late, 0);
});
}
const map = createAndSetupMap(assignment, studentWithoutSubmission)
const submission = map.getSubmission(studentWithoutSubmission.id, assignment.id)
strictEqual(submission.seconds_late, 0)
})
test('the submission object has late set to false', function() {
const assignment = {
id: '1',
published: true,
effectiveDueDates: {1: {due_at: new Date()}}
};
const map = createAndSetupMap(assignment, studentWithoutSubmission);
const submission = map.getSubmission(studentWithoutSubmission.id, assignment.id);
strictEqual(submission.late, false);
});
}
const map = createAndSetupMap(assignment, studentWithoutSubmission)
const submission = map.getSubmission(studentWithoutSubmission.id, assignment.id)
strictEqual(submission.late, false)
})
test('the submission object has excused set to false', function() {
const assignment = {
id: '1',
published: true,
effectiveDueDates: {1: {due_at: new Date()}}
};
const map = createAndSetupMap(assignment, studentWithoutSubmission);
const submission = map.getSubmission(studentWithoutSubmission.id, assignment.id);
strictEqual(submission.excused, false);
});
});
}
const map = createAndSetupMap(assignment, studentWithoutSubmission)
const submission = map.getSubmission(studentWithoutSubmission.id, assignment.id)
strictEqual(submission.excused, false)
})
})
test('an unpublished assignment is locked and grades are hidden', () => {
const map = createAndSetupMap(unpublishedAssignment.toJS(), studentWithoutSubmission)
@ -334,7 +394,10 @@ QUnit.module('#setSubmissionCellState', function() {
})
test('a moderated and unpublished grades assignment is locked and grades not hidden when published', () => {
const map = createAndSetupMap(moderatedAndGradesUnpublishedAssignment.toJS(), studentWithoutSubmission)
const map = createAndSetupMap(
moderatedAndGradesUnpublishedAssignment.toJS(),
studentWithoutSubmission
)
const submission = map.getSubmissionState({
user_id: studentWithoutSubmission.id,
assignment_id: moderatedAndGradesUnpublishedAssignment.get('id')
@ -367,35 +430,54 @@ QUnit.module('#setSubmissionCellState', function() {
test('is unpublished takes precedence over one that is moderated and has unpublished grades', () => {
const assignment = moderatedAndGradesUnpublishedAssignment.merge(unpublishedAssignment)
const map = createAndSetupMap(assignment.toJS(), studentWithSubmission)
const submission = map.getSubmissionState({user_id: studentWithSubmission.id, assignment_id: assignment.get('id')})
const submission = map.getSubmissionState({
user_id: studentWithSubmission.id,
assignment_id: assignment.get('id')
})
deepEqual(submission, {locked: true, hideGrade: true})
})
test('is anonymously graded and muted takes precedence over one that is moderated and has unpublished grades', () => {
const assignment = moderatedAndGradesUnpublishedAssignment.merge(anonymousMutedAssignment)
const map = createAndSetupMap(assignment.toJS(), studentWithSubmission)
const submission = map.getSubmissionState({user_id: studentWithSubmission.id, assignment_id: assignment.get('id')})
const submission = map.getSubmissionState({
user_id: studentWithSubmission.id,
assignment_id: assignment.get('id')
})
deepEqual(submission, {locked: true, hideGrade: true})
})
test('is moderated and has unpublished grades takes precedence over one that is hidden from the student', () => {
const assignment = hiddenFromStudent.merge(moderatedAndGradesUnpublishedAssignment)
const map = createAndSetupMap(assignment.toJS(), studentWithSubmission)
const submission = map.getSubmissionState({user_id: studentWithSubmission.id, assignment_id: assignment.get('id')})
const submission = map.getSubmissionState({
user_id: studentWithSubmission.id,
assignment_id: assignment.get('id')
})
deepEqual(submission, {locked: true, hideGrade: false})
})
test('is hidden from the student takes precendence over one that has grading periods', () => {
const assignment = hasGradingPeriodsAssignment.merge(hiddenFromStudent)
const map = createAndSetupMap(assignment.toJS(), studentWithSubmission, {hasGradingPeriods: true})
const submission = map.getSubmissionState({user_id: studentWithSubmission.id, assignment_id: assignment.get('id')})
const map = createAndSetupMap(assignment.toJS(), studentWithSubmission, {
hasGradingPeriods: true
})
const submission = map.getSubmissionState({
user_id: studentWithSubmission.id,
assignment_id: assignment.get('id')
})
deepEqual(submission, {locked: true, hideGrade: true})
})
test('has grading periods takes precendence over all other assignments', () => {
const assignment = hasGradingPeriodsAssignment.merge(baseAssignment)
const map = createAndSetupMap(assignment.toJS(), studentWithSubmission, {hasGradingPeriods: true})
const actualSubmissionState = map.getSubmissionState({user_id: studentWithSubmission.id, assignment_id: assignment.get('id')})
const map = createAndSetupMap(assignment.toJS(), studentWithSubmission, {
hasGradingPeriods: true
})
const actualSubmissionState = map.getSubmissionState({
user_id: studentWithSubmission.id,
assignment_id: assignment.get('id')
})
const expectedSubmissionState = {
locked: true,
hideGrade: false,
@ -407,4 +489,4 @@ QUnit.module('#setSubmissionCellState', function() {
})
})
})
});
})

View File

@ -26,7 +26,8 @@ define([
QUnit.module('CurveGradesDialogManager.createCurveGradesAction.isDisabled', {
props({points_possible, grading_type, submissionsLoaded}) {
return [
{ // assignment
{
// assignment
points_possible,
grading_type
},
@ -36,47 +37,73 @@ define([
contextUrl: 'http://contextUrl/',
submissionsLoaded
}
];
]
}
});
})
test('is not disabled when submissions are loaded, grading type is not pass/fail and there are ' +
'points that are not 0', function () {
const props = this.props({points_possible: 10, grading_type: 'points', submissionsLoaded: true});
notOk(createCurveGradesAction(...props).isDisabled);
});
test(
'is not disabled when submissions are loaded, grading type is not pass/fail and there are ' +
'points that are not 0',
function() {
const props = this.props({
points_possible: 10,
grading_type: 'points',
submissionsLoaded: true
})
notOk(createCurveGradesAction(...props).isDisabled)
}
)
test('is disabled when submissions are not loaded', function() {
const props = this.props({points_possible: 10, grading_type: 'points', submissionsLoaded: false });
ok(createCurveGradesAction(...props).isDisabled);
});
const props = this.props({
points_possible: 10,
grading_type: 'points',
submissionsLoaded: false
})
ok(createCurveGradesAction(...props).isDisabled)
})
test('is disabled when grading type is pass/fail', function() {
const props = this.props({points_possible: 10, grading_type: 'pass_fail', submissionsLoaded: true });
ok(createCurveGradesAction(...props).isDisabled);
});
const props = this.props({
points_possible: 10,
grading_type: 'pass_fail',
submissionsLoaded: true
})
ok(createCurveGradesAction(...props).isDisabled)
})
test('returns true when points_possible is null', function() {
const props = this.props({points_possible: null, grading_type: 'points', submissionsLoaded: true});
ok(createCurveGradesAction(...props).isDisabled);
});
const props = this.props({
points_possible: null,
grading_type: 'points',
submissionsLoaded: true
})
ok(createCurveGradesAction(...props).isDisabled)
})
test('returns true when points_possible is 0', function() {
const props = this.props({points_possible: 0, grading_type: 'points', submissionsLoaded: true});
ok(createCurveGradesAction(...props).isDisabled);
});
const props = this.props({points_possible: 0, grading_type: 'points', submissionsLoaded: true})
ok(createCurveGradesAction(...props).isDisabled)
})
QUnit.module('CurveGradesDialogManager.createCurveGradesAction.onSelect', {
setup() {
this.flashErrorSpy = sandbox.spy($, 'flashError');
sandbox.stub(CurveGradesDialog.prototype, 'show');
this.flashErrorSpy = sandbox.spy($, 'flashError')
sandbox.stub(CurveGradesDialog.prototype, 'show')
},
onSelect({isAdmin = false, inClosedGradingPeriod = false} = {}) {
createCurveGradesAction({ inClosedGradingPeriod }, [], isAdmin, 'http://contextUrl/', true).onSelect()
createCurveGradesAction(
{inClosedGradingPeriod},
[],
isAdmin,
'http://contextUrl/',
true
).onSelect()
},
props({inClosedGradingPeriod = false, isAdmin = false} = {}) {
return [
{ // assignment
{
// assignment
inClosedGradingPeriod
},
[], // students
@ -85,56 +112,62 @@ define([
contextUrl: 'http://contextUrl/',
submissionsLoaded: true
}
];
]
}
});
})
test('calls flashError if is not admin and in a closed grading period', function() {
const props = this.props({ isAdmin: false, inClosedGradingPeriod: true });
createCurveGradesAction(...props).onSelect();
ok(this.flashErrorSpy.withArgs(I18n.t('Unable to curve grades because this assignment is due in a closed ' +
'grading period for at least one student')).calledOnce);
});
const props = this.props({isAdmin: false, inClosedGradingPeriod: true})
createCurveGradesAction(...props).onSelect()
ok(
this.flashErrorSpy.withArgs(
I18n.t(
'Unable to curve grades because this assignment is due in a closed ' +
'grading period for at least one student'
)
).calledOnce
)
})
test('does not call curve grades dialog if is not admin and in a closed grading period', function() {
const props = this.props({ isAdmin: false, inClosedGradingPeriod: true });
createCurveGradesAction(...props).onSelect();
strictEqual(CurveGradesDialog.prototype.show.callCount, 0);
});
const props = this.props({isAdmin: false, inClosedGradingPeriod: true})
createCurveGradesAction(...props).onSelect()
strictEqual(CurveGradesDialog.prototype.show.callCount, 0)
})
test('does not call flashError if is admin and in a closed grading period', function() {
const props = this.props({ isAdmin: true, inClosedGradingPeriod: true });
createCurveGradesAction(...props).onSelect();
ok(this.flashErrorSpy.notCalled);
});
const props = this.props({isAdmin: true, inClosedGradingPeriod: true})
createCurveGradesAction(...props).onSelect()
ok(this.flashErrorSpy.notCalled)
})
test('calls curve grades dialog if is admin and in a closed grading period', function() {
const props = this.props({ isAdmin: true, inClosedGradingPeriod: true });
createCurveGradesAction(...props).onSelect();
strictEqual(CurveGradesDialog.prototype.show.callCount, 1);
});
const props = this.props({isAdmin: true, inClosedGradingPeriod: true})
createCurveGradesAction(...props).onSelect()
strictEqual(CurveGradesDialog.prototype.show.callCount, 1)
})
test('does not call flashError if is not admin and not in a closed grading period', function() {
const props = this.props({ isAdmin: false, inClosedGradingPeriod: false });
createCurveGradesAction(...props).onSelect();
ok(this.flashErrorSpy.notCalled);
});
const props = this.props({isAdmin: false, inClosedGradingPeriod: false})
createCurveGradesAction(...props).onSelect()
ok(this.flashErrorSpy.notCalled)
})
test('calls curve grades dialog if is not admin and not in a closed grading period', function() {
const props = this.props({ isAdmin: false, inClosedGradingPeriod: false });
createCurveGradesAction(...props).onSelect();
strictEqual(CurveGradesDialog.prototype.show.callCount, 1);
});
const props = this.props({isAdmin: false, inClosedGradingPeriod: false})
createCurveGradesAction(...props).onSelect()
strictEqual(CurveGradesDialog.prototype.show.callCount, 1)
})
test('does not call flashError if is admin and not in a closed grading period', function() {
const props = this.props({ isAdmin: true, inClosedGradingPeriod: false });
createCurveGradesAction(...props).onSelect();
ok(this.flashErrorSpy.notCalled);
});
const props = this.props({isAdmin: true, inClosedGradingPeriod: false})
createCurveGradesAction(...props).onSelect()
ok(this.flashErrorSpy.notCalled)
})
test('calls curve grades dialog if is admin and not in a closed grading period', function() {
const props = this.props({ isAdmin: true, inClosedGradingPeriod: false });
createCurveGradesAction(...props).onSelect();
strictEqual(CurveGradesDialog.prototype.show.callCount, 1);
});
});
const props = this.props({isAdmin: true, inClosedGradingPeriod: false})
createCurveGradesAction(...props).onSelect()
strictEqual(CurveGradesDialog.prototype.show.callCount, 1)
})
})

View File

@ -16,25 +16,25 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import $ from 'jquery';
import fakeENV from 'helpers/fakeENV';
import DataLoader from 'jsx/gradezilla/DataLoader';
import $ from 'jquery'
import fakeENV from 'helpers/fakeENV'
import DataLoader from 'jsx/gradezilla/DataLoader'
import {
createGradebook,
setFixtureHtml
} from 'jsx/gradezilla/default_gradebook/__tests__/GradebookSpecHelper';
} from 'jsx/gradezilla/default_gradebook/__tests__/GradebookSpecHelper'
import SlickGridSpecHelper from '../../gradezilla/default_gradebook/GradebookGrid/GridSupport/SlickGridSpecHelper'
QUnit.module('Gradebook Grid Column Filtering', function(suiteHooks) {
let $fixture;
let gridSpecHelper;
let gradebook;
let dataLoader;
let $fixture
let gridSpecHelper
let gradebook
let dataLoader
let assignmentGroups;
let assignments;
let contextModules;
let customColumns;
let assignmentGroups
let assignments
let contextModules
let customColumns
function createGradebookWithAllFilters(options = {}) {
gradebook = createGradebook({
@ -53,19 +53,20 @@ QUnit.module('Gradebook Grid Column Filtering', function (suiteHooks) {
{id: '2601', position: 3, name: 'Final Module'},
{id: '2602', position: 2, name: 'Second Module'},
{id: '2603', position: 1, name: 'First Module'}
];
]
}
function createCustomColumns() {
customColumns = [
{id: '2401', teacher_notes: true, title: 'Notes'},
{id: '2402', teacher_notes: false, title: 'Other Notes'}
];
]
}
function createAssignments() {
assignments = {
homework: [{
homework: [
{
id: '2301',
assignment_group_id: '2201',
course_id: '1201',
@ -80,7 +81,8 @@ QUnit.module('Gradebook Grid Column Filtering', function (suiteHooks) {
position: 1,
published: true,
submission_types: ['online_text_entry']
}, {
},
{
id: '2303',
assignment_group_id: '2201',
course_id: '1201',
@ -95,9 +97,11 @@ QUnit.module('Gradebook Grid Column Filtering', function (suiteHooks) {
position: 2,
published: true,
submission_types: ['online_text_entry']
}],
}
],
quizzes: [{
quizzes: [
{
id: '2302',
assignment_group_id: '2202',
course_id: '1201',
@ -112,7 +116,8 @@ QUnit.module('Gradebook Grid Column Filtering', function (suiteHooks) {
position: 1,
published: true,
submission_types: ['online_quiz']
}, {
},
{
id: '2304',
assignment_group_id: '2202',
course_id: '1201',
@ -127,63 +132,64 @@ QUnit.module('Gradebook Grid Column Filtering', function (suiteHooks) {
position: 2,
published: true,
submission_types: ['online_quiz']
}]
};
}
]
}
}
function createAssignmentGroups() {
assignmentGroups = [
{id: '2201', position: 2, name: 'Homework', assignments: assignments.homework},
{id: '2202', position: 1, name: 'Quizzes', assignments: assignments.quizzes}
];
]
}
function addStudentIds() {
dataLoader.gotStudentIds.resolve({
user_ids: ['1101']
});
})
}
function addGradingPeriodAssignments() {
dataLoader.gotGradingPeriodAssignments.resolve({
grading_period_assignments: {1401: ['2301', '2304'], 1402: ['2302', '2303']}
});
})
}
function addContextModules() {
dataLoader.gotContextModules.resolve(contextModules);
dataLoader.gotContextModules.resolve(contextModules)
}
function addCustomColumns() {
dataLoader.gotCustomColumns.resolve(customColumns);
dataLoader.gotCustomColumns.resolve(customColumns)
}
function addAssignmentGroups() {
dataLoader.gotAssignmentGroups.resolve(assignmentGroups);
dataLoader.gotAssignmentGroups.resolve(assignmentGroups)
}
function addGridData() {
addStudentIds();
addContextModules();
addCustomColumns();
addAssignmentGroups();
addGradingPeriodAssignments();
addStudentIds()
addContextModules()
addCustomColumns()
addAssignmentGroups()
addGradingPeriodAssignments()
}
function addDataAndInitialize() {
gradebook.initialize();
addGridData();
gridSpecHelper = new SlickGridSpecHelper(gradebook.gradebookGrid);
gradebook.initialize()
addGridData()
gridSpecHelper = new SlickGridSpecHelper(gradebook.gradebookGrid)
}
suiteHooks.beforeEach(function() {
$fixture = document.createElement('div');
document.body.appendChild($fixture);
setFixtureHtml($fixture);
$fixture = document.createElement('div')
document.body.appendChild($fixture)
setFixtureHtml($fixture)
fakeENV.setup({
current_user_id: '1101'
});
})
dataLoader = {
gotAssignmentGroups: $.Deferred(),
@ -194,217 +200,310 @@ QUnit.module('Gradebook Grid Column Filtering', function (suiteHooks) {
gotStudentIds: $.Deferred(),
gotStudents: $.Deferred(),
gotSubmissions: $.Deferred()
};
sinon.stub(DataLoader, 'loadGradebookData').returns(dataLoader);
sinon.stub(DataLoader, 'getDataForColumn');
}
sinon.stub(DataLoader, 'loadGradebookData').returns(dataLoader)
sinon.stub(DataLoader, 'getDataForColumn')
createAssignments();
createAssignmentGroups();
createContextModules();
createCustomColumns();
});
createAssignments()
createAssignmentGroups()
createContextModules()
createCustomColumns()
})
suiteHooks.afterEach(function() {
gradebook.destroy();
DataLoader.loadGradebookData.restore();
DataLoader.getDataForColumn.restore();
fakeENV.teardown();
$fixture.remove();
});
gradebook.destroy()
DataLoader.loadGradebookData.restore()
DataLoader.getDataForColumn.restore()
fakeENV.teardown()
$fixture.remove()
})
QUnit.module('with unpublished assignments', function(hooks) {
function setShowUnpublishedAssignments(show) {
gradebook.gridDisplaySettings.showUnpublishedAssignments = show;
gradebook.gridDisplaySettings.showUnpublishedAssignments = show
}
hooks.beforeEach(function() {
assignments.homework[1].published = false;
assignments.quizzes[1].published = false;
assignments.homework[1].published = false
assignments.quizzes[1].published = false
createGradebookWithAllFilters()
});
})
test('optionally shows all unpublished assignment columns at initial render', function() {
setShowUnpublishedAssignments(true);
addDataAndInitialize();
setShowUnpublishedAssignments(true)
addDataAndInitialize()
const expectedColumns = [
'assignment_2301', 'assignment_2302', 'assignment_2303', 'assignment_2304',
'assignment_group_2201', 'assignment_group_2202', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns);
});
'assignment_2301',
'assignment_2302',
'assignment_2303',
'assignment_2304',
'assignment_group_2201',
'assignment_group_2202',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns)
})
test('optionally hides all unpublished assignment columns at initial render', function() {
setShowUnpublishedAssignments(false);
addDataAndInitialize();
setShowUnpublishedAssignments(false)
addDataAndInitialize()
const expectedColumns = [
'assignment_2301', 'assignment_2302', 'assignment_group_2201', 'assignment_group_2202', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns);
});
'assignment_2301',
'assignment_2302',
'assignment_group_2201',
'assignment_group_2202',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns)
})
test('optionally shows all unpublished assignment columns', function() {
setShowUnpublishedAssignments(false);
addDataAndInitialize();
gradebook.toggleUnpublishedAssignments();
setShowUnpublishedAssignments(false)
addDataAndInitialize()
gradebook.toggleUnpublishedAssignments()
const expectedColumns = [
'assignment_2301', 'assignment_2302', 'assignment_2303', 'assignment_2304',
'assignment_group_2201', 'assignment_group_2202', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns);
});
'assignment_2301',
'assignment_2302',
'assignment_2303',
'assignment_2304',
'assignment_group_2201',
'assignment_group_2202',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns)
})
test('optionally hides all unpublished assignment columns', function() {
setShowUnpublishedAssignments(true);
addDataAndInitialize();
gradebook.toggleUnpublishedAssignments();
setShowUnpublishedAssignments(true)
addDataAndInitialize()
gradebook.toggleUnpublishedAssignments()
const expectedColumns = [
'assignment_2301', 'assignment_2302', 'assignment_group_2201', 'assignment_group_2202', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns);
});
'assignment_2301',
'assignment_2302',
'assignment_group_2201',
'assignment_group_2202',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns)
})
test('sorts all scrollable columns after showing unpublished assignment columns', function() {
const customOrder = [
'student', 'custom_col_2401', 'custom_col_2402', 'total_grade', 'assignment_group_2201', 'assignment_2301',
'assignment_2303', 'assignment_group_2202', 'assignment_2302', 'assignment_2304'
];
setShowUnpublishedAssignments(true);
addDataAndInitialize();
gridSpecHelper.updateColumnOrder(customOrder);
gradebook.toggleUnpublishedAssignments(); // hide unpublished
gradebook.toggleUnpublishedAssignments(); // show unpublished
deepEqual(gridSpecHelper.listColumnIds(), customOrder);
});
'student',
'custom_col_2401',
'custom_col_2402',
'total_grade',
'assignment_group_2201',
'assignment_2301',
'assignment_2303',
'assignment_group_2202',
'assignment_2302',
'assignment_2304'
]
setShowUnpublishedAssignments(true)
addDataAndInitialize()
gridSpecHelper.updateColumnOrder(customOrder)
gradebook.toggleUnpublishedAssignments() // hide unpublished
gradebook.toggleUnpublishedAssignments() // show unpublished
deepEqual(gridSpecHelper.listColumnIds(), customOrder)
})
test('sorts all scrollable columns after hiding unpublished assignment columns', function() {
const customOrder = [
'student', 'custom_col_2401', 'custom_col_2402', 'total_grade', 'assignment_group_2201', 'assignment_2301',
'assignment_2303', 'assignment_group_2202', 'assignment_2302', 'assignment_2304'
];
setShowUnpublishedAssignments(true);
addDataAndInitialize();
gridSpecHelper.updateColumnOrder(customOrder);
gradebook.toggleUnpublishedAssignments();
'student',
'custom_col_2401',
'custom_col_2402',
'total_grade',
'assignment_group_2201',
'assignment_2301',
'assignment_2303',
'assignment_group_2202',
'assignment_2302',
'assignment_2304'
]
setShowUnpublishedAssignments(true)
addDataAndInitialize()
gridSpecHelper.updateColumnOrder(customOrder)
gradebook.toggleUnpublishedAssignments()
const expectedColumns = [
'student', 'custom_col_2401', 'custom_col_2402', 'total_grade', 'assignment_group_2201', 'assignment_2301',
'assignment_group_2202', 'assignment_2302'
];
deepEqual(gridSpecHelper.listColumnIds(), expectedColumns);
});
});
'student',
'custom_col_2401',
'custom_col_2402',
'total_grade',
'assignment_group_2201',
'assignment_2301',
'assignment_group_2202',
'assignment_2302'
]
deepEqual(gridSpecHelper.listColumnIds(), expectedColumns)
})
})
QUnit.module('with attendance assignments', function(hooks) {
function setShowAttendance(show) {
gradebook.show_attendance = show;
gradebook.show_attendance = show
}
hooks.beforeEach(function() {
assignments.homework[0].submission_types = ['attendance'];
assignments.homework[1].submission_types = ['attendance'];
assignments.homework[0].submission_types = ['attendance']
assignments.homework[1].submission_types = ['attendance']
createGradebookWithAllFilters()
});
})
test('optionally shows all attendance assignment columns at initial render', function() {
setShowAttendance(true);
addDataAndInitialize();
setShowAttendance(true)
addDataAndInitialize()
const expectedColumns = [
'assignment_2301', 'assignment_2302', 'assignment_2303', 'assignment_2304',
'assignment_group_2201', 'assignment_group_2202', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns);
});
'assignment_2301',
'assignment_2302',
'assignment_2303',
'assignment_2304',
'assignment_group_2201',
'assignment_group_2202',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns)
})
test('optionally hides all attendance assignment columns at initial render', function() {
setShowAttendance(false);
addDataAndInitialize();
setShowAttendance(false)
addDataAndInitialize()
const expectedColumns = [
'assignment_2302', 'assignment_2304', 'assignment_group_2201', 'assignment_group_2202', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns);
});
});
'assignment_2302',
'assignment_2304',
'assignment_group_2201',
'assignment_group_2202',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns)
})
})
test('does not show "not graded" assignments', function() {
assignments.homework[1].submission_types = ['not_graded'];
assignments.quizzes[1].submission_types = ['not_graded'];
createGradebookWithAllFilters();
addDataAndInitialize();
assignments.homework[1].submission_types = ['not_graded']
assignments.quizzes[1].submission_types = ['not_graded']
createGradebookWithAllFilters()
addDataAndInitialize()
const expectedColumns = [
'assignment_2301', 'assignment_2302', 'assignment_group_2201', 'assignment_group_2202', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns);
});
'assignment_2301',
'assignment_2302',
'assignment_group_2201',
'assignment_group_2202',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns)
})
QUnit.module('with multiple assignment groups', function(hooks) {
hooks.beforeEach(function() {
createGradebookWithAllFilters()
});
})
test('optionally shows assignment columns for all assignment groups at initial render', function() {
addDataAndInitialize();
addDataAndInitialize()
gradebook.updateCurrentAssignmentGroup('0')
const expectedColumns = [
'assignment_2301', 'assignment_2302', 'assignment_2303', 'assignment_2304',
'assignment_group_2201', 'assignment_group_2202', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns);
});
'assignment_2301',
'assignment_2302',
'assignment_2303',
'assignment_2304',
'assignment_group_2201',
'assignment_group_2202',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns)
})
test('optionally shows only assignment columns for the selected assignment group at initial render', function() {
addDataAndInitialize();
addDataAndInitialize()
gradebook.updateCurrentAssignmentGroup('2201')
const expectedColumns = [
'assignment_2301', 'assignment_2303', 'assignment_group_2201', 'assignment_group_2202', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns);
});
'assignment_2301',
'assignment_2303',
'assignment_group_2201',
'assignment_group_2202',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns)
})
test('optionally shows assignment columns for all assignment groups', function() {
addDataAndInitialize();
gradebook.updateCurrentAssignmentGroup('0');
addDataAndInitialize()
gradebook.updateCurrentAssignmentGroup('0')
const expectedColumns = [
'assignment_2301', 'assignment_2302', 'assignment_2303', 'assignment_2304',
'assignment_group_2201', 'assignment_group_2202', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns);
});
'assignment_2301',
'assignment_2302',
'assignment_2303',
'assignment_2304',
'assignment_group_2201',
'assignment_group_2202',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns)
})
test('optionally shows only assignment columns for the selected assignment group', function() {
addDataAndInitialize();
gradebook.updateCurrentAssignmentGroup('2202');
addDataAndInitialize()
gradebook.updateCurrentAssignmentGroup('2202')
const expectedColumns = [
'assignment_2302', 'assignment_2304', 'assignment_group_2201', 'assignment_group_2202', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns);
});
'assignment_2302',
'assignment_2304',
'assignment_group_2201',
'assignment_group_2202',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns)
})
test('sorts all scrollable columns after selecting an assignment group', function() {
const customOrder = [
'student', 'custom_col_2401', 'custom_col_2402', 'total_grade', 'assignment_group_2201', 'assignment_2301',
'assignment_2303', 'assignment_group_2202', 'assignment_2302', 'assignment_2304'
];
addDataAndInitialize();
gridSpecHelper.updateColumnOrder(customOrder);
gradebook.updateCurrentAssignmentGroup('2202');
'student',
'custom_col_2401',
'custom_col_2402',
'total_grade',
'assignment_group_2201',
'assignment_2301',
'assignment_2303',
'assignment_group_2202',
'assignment_2302',
'assignment_2304'
]
addDataAndInitialize()
gridSpecHelper.updateColumnOrder(customOrder)
gradebook.updateCurrentAssignmentGroup('2202')
const expectedColumns = [
'student', 'custom_col_2401', 'custom_col_2402', 'total_grade', 'assignment_group_2201',
'assignment_group_2202', 'assignment_2302', 'assignment_2304'
];
deepEqual(gridSpecHelper.listColumnIds(), expectedColumns);
});
'student',
'custom_col_2401',
'custom_col_2402',
'total_grade',
'assignment_group_2201',
'assignment_group_2202',
'assignment_2302',
'assignment_2304'
]
deepEqual(gridSpecHelper.listColumnIds(), expectedColumns)
})
test('sorts all scrollable columns after deselecting an assignment group', function() {
const customOrder = [
'student', 'custom_col_2401', 'custom_col_2402', 'total_grade', 'assignment_group_2201', 'assignment_2301',
'assignment_2303', 'assignment_group_2202', 'assignment_2302', 'assignment_2304'
];
addDataAndInitialize();
gridSpecHelper.updateColumnOrder(customOrder);
gradebook.updateCurrentAssignmentGroup('2202');
gradebook.updateCurrentAssignmentGroup('0');
deepEqual(gridSpecHelper.listColumnIds(), customOrder);
});
});
'student',
'custom_col_2401',
'custom_col_2402',
'total_grade',
'assignment_group_2201',
'assignment_2301',
'assignment_2303',
'assignment_group_2202',
'assignment_2302',
'assignment_2304'
]
addDataAndInitialize()
gridSpecHelper.updateColumnOrder(customOrder)
gradebook.updateCurrentAssignmentGroup('2202')
gradebook.updateCurrentAssignmentGroup('0')
deepEqual(gridSpecHelper.listColumnIds(), customOrder)
})
})
QUnit.module('with grading periods', function(hooks) {
hooks.beforeEach(function() {
@ -414,163 +513,248 @@ QUnit.module('Gradebook Grid Column Filtering', function (suiteHooks) {
display_totals_for_all_grading_periods: true,
grading_periods: [{id: '1401', title: 'GP1'}, {id: '1402', title: 'GP2'}]
}
});
});
})
})
test('optionally shows assignment columns for all grading periods at initial render', function() {
gradebook.setFilterColumnsBySetting('gradingPeriodId', '0');
addDataAndInitialize();
gradebook.setFilterColumnsBySetting('gradingPeriodId', '0')
addDataAndInitialize()
const expectedColumns = [
'assignment_2301', 'assignment_2302', 'assignment_2303', 'assignment_2304',
'assignment_group_2201', 'assignment_group_2202', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns);
});
'assignment_2301',
'assignment_2302',
'assignment_2303',
'assignment_2304',
'assignment_group_2201',
'assignment_group_2202',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns)
})
test('optionally shows only assignment columns for the selected grading period at initial render', function() {
gradebook.setFilterColumnsBySetting('gradingPeriodId', '1401');
addDataAndInitialize();
gradebook.setFilterColumnsBySetting('gradingPeriodId', '1401')
addDataAndInitialize()
const expectedColumns = [
'assignment_2301', 'assignment_2304', 'assignment_group_2201', 'assignment_group_2202', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns);
});
'assignment_2301',
'assignment_2304',
'assignment_group_2201',
'assignment_group_2202',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns)
})
test('optionally shows assignment columns for all grading periods', function() {
addDataAndInitialize();
gradebook.updateCurrentGradingPeriod('0');
addDataAndInitialize()
gradebook.updateCurrentGradingPeriod('0')
const expectedColumns = [
'assignment_2301', 'assignment_2302', 'assignment_2303', 'assignment_2304',
'assignment_group_2201', 'assignment_group_2202', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns);
});
'assignment_2301',
'assignment_2302',
'assignment_2303',
'assignment_2304',
'assignment_group_2201',
'assignment_group_2202',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns)
})
test('optionally shows only assignment columns for the selected grading period', function() {
addDataAndInitialize();
gradebook.updateCurrentGradingPeriod('1402');
addDataAndInitialize()
gradebook.updateCurrentGradingPeriod('1402')
const expectedColumns = [
'assignment_2302', 'assignment_2303', 'assignment_group_2201', 'assignment_group_2202', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns);
});
'assignment_2302',
'assignment_2303',
'assignment_group_2201',
'assignment_group_2202',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns)
})
test('optionally hides assignment group and total grade columns when filtering at initial render', function() {
gradebook.gradingPeriodSet.displayTotalsForAllGradingPeriods = false;
addDataAndInitialize();
gradebook.setFilterColumnsBySetting('gradingPeriodId', '0');
gradebook.gradingPeriodSet.displayTotalsForAllGradingPeriods = false
addDataAndInitialize()
gradebook.setFilterColumnsBySetting('gradingPeriodId', '0')
const expectedColumns = [
'assignment_2301', 'assignment_2302', 'assignment_2303', 'assignment_2304'
];
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns);
});
'assignment_2301',
'assignment_2302',
'assignment_2303',
'assignment_2304'
]
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns)
})
test('optionally hides assignment group and total grade columns when filtering', function() {
gradebook.gradingPeriodSet.displayTotalsForAllGradingPeriods = false;
addDataAndInitialize();
gradebook.updateCurrentGradingPeriod('0');
gradebook.gradingPeriodSet.displayTotalsForAllGradingPeriods = false
addDataAndInitialize()
gradebook.updateCurrentGradingPeriod('0')
const expectedColumns = [
'assignment_2301', 'assignment_2302', 'assignment_2303', 'assignment_2304'
];
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns);
});
'assignment_2301',
'assignment_2302',
'assignment_2303',
'assignment_2304'
]
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns)
})
test('sorts all scrollable columns after selecting a grading period', function() {
const customOrder = [
'student', 'custom_col_2401', 'custom_col_2402', 'total_grade', 'assignment_group_2201', 'assignment_2301',
'assignment_2303', 'assignment_group_2202', 'assignment_2302', 'assignment_2304'
];
addDataAndInitialize();
gridSpecHelper.updateColumnOrder(customOrder);
gradebook.updateCurrentGradingPeriod('1402');
'student',
'custom_col_2401',
'custom_col_2402',
'total_grade',
'assignment_group_2201',
'assignment_2301',
'assignment_2303',
'assignment_group_2202',
'assignment_2302',
'assignment_2304'
]
addDataAndInitialize()
gridSpecHelper.updateColumnOrder(customOrder)
gradebook.updateCurrentGradingPeriod('1402')
const expectedColumns = [
'student', 'custom_col_2401', 'custom_col_2402', 'total_grade', 'assignment_group_2201',
'assignment_2303', 'assignment_group_2202', 'assignment_2302'
];
deepEqual(gridSpecHelper.listColumnIds(), expectedColumns);
});
'student',
'custom_col_2401',
'custom_col_2402',
'total_grade',
'assignment_group_2201',
'assignment_2303',
'assignment_group_2202',
'assignment_2302'
]
deepEqual(gridSpecHelper.listColumnIds(), expectedColumns)
})
test('sorts all scrollable columns after deselecting a grading period', function() {
const customOrder = [
'student', 'custom_col_2401', 'custom_col_2402', 'total_grade', 'assignment_group_2201', 'assignment_2301',
'assignment_2303', 'assignment_group_2202', 'assignment_2302', 'assignment_2304'
];
addDataAndInitialize();
gridSpecHelper.updateColumnOrder(customOrder);
gradebook.updateCurrentGradingPeriod('1402');
gradebook.updateCurrentGradingPeriod('0');
deepEqual(gridSpecHelper.listColumnIds(), customOrder);
});
});
'student',
'custom_col_2401',
'custom_col_2402',
'total_grade',
'assignment_group_2201',
'assignment_2301',
'assignment_2303',
'assignment_group_2202',
'assignment_2302',
'assignment_2304'
]
addDataAndInitialize()
gridSpecHelper.updateColumnOrder(customOrder)
gradebook.updateCurrentGradingPeriod('1402')
gradebook.updateCurrentGradingPeriod('0')
deepEqual(gridSpecHelper.listColumnIds(), customOrder)
})
})
QUnit.module('with multiple context modules', function(hooks) {
hooks.beforeEach(function() {
createGradebookWithAllFilters()
});
})
test('optionally shows assignment columns for all context modules at initial render', function() {
gradebook.setFilterColumnsBySetting('contextModuleId', '0');
addDataAndInitialize();
gradebook.setFilterColumnsBySetting('contextModuleId', '0')
addDataAndInitialize()
const expectedColumns = [
'assignment_2301', 'assignment_2302', 'assignment_2303', 'assignment_2304',
'assignment_group_2201', 'assignment_group_2202', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns);
});
'assignment_2301',
'assignment_2302',
'assignment_2303',
'assignment_2304',
'assignment_group_2201',
'assignment_group_2202',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns)
})
test('optionally shows only assignment columns for the selected context module at initial render', function() {
gradebook.setFilterColumnsBySetting('contextModuleId', '2601');
addDataAndInitialize();
gradebook.setFilterColumnsBySetting('contextModuleId', '2601')
addDataAndInitialize()
const expectedColumns = [
'assignment_2301', 'assignment_2303', 'assignment_group_2201', 'assignment_group_2202', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns);
});
'assignment_2301',
'assignment_2303',
'assignment_group_2201',
'assignment_group_2202',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns)
})
test('optionally shows assignment columns for all context modules', function() {
addDataAndInitialize();
gradebook.updateCurrentModule('0');
addDataAndInitialize()
gradebook.updateCurrentModule('0')
const expectedColumns = [
'assignment_2301', 'assignment_2302', 'assignment_2303', 'assignment_2304',
'assignment_group_2201', 'assignment_group_2202', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns);
});
'assignment_2301',
'assignment_2302',
'assignment_2303',
'assignment_2304',
'assignment_group_2201',
'assignment_group_2202',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns)
})
test('optionally shows only assignment columns for the selected context module', function() {
addDataAndInitialize();
gradebook.updateCurrentModule('2602');
addDataAndInitialize()
gradebook.updateCurrentModule('2602')
const expectedColumns = [
'assignment_2302', 'assignment_group_2201', 'assignment_group_2202', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns);
});
'assignment_2302',
'assignment_group_2201',
'assignment_group_2202',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds().sort(), expectedColumns)
})
test('sorts all scrollable columns after selecting a context module', function() {
const customOrder = [
'student', 'custom_col_2401', 'custom_col_2402', 'total_grade', 'assignment_group_2201', 'assignment_2301',
'assignment_2303', 'assignment_group_2202', 'assignment_2302', 'assignment_2304'
];
addDataAndInitialize();
gridSpecHelper.updateColumnOrder(customOrder);
gradebook.updateCurrentModule('2601');
'student',
'custom_col_2401',
'custom_col_2402',
'total_grade',
'assignment_group_2201',
'assignment_2301',
'assignment_2303',
'assignment_group_2202',
'assignment_2302',
'assignment_2304'
]
addDataAndInitialize()
gridSpecHelper.updateColumnOrder(customOrder)
gradebook.updateCurrentModule('2601')
const expectedColumns = [
'student', 'custom_col_2401', 'custom_col_2402', 'total_grade', 'assignment_group_2201', 'assignment_2301',
'assignment_2303', 'assignment_group_2202'
];
deepEqual(gridSpecHelper.listColumnIds(), expectedColumns);
});
'student',
'custom_col_2401',
'custom_col_2402',
'total_grade',
'assignment_group_2201',
'assignment_2301',
'assignment_2303',
'assignment_group_2202'
]
deepEqual(gridSpecHelper.listColumnIds(), expectedColumns)
})
test('sorts all scrollable columns after deselecting a context module', function() {
const customOrder = [
'student', 'custom_col_2401', 'custom_col_2402', 'total_grade', 'assignment_group_2201', 'assignment_2301',
'assignment_2303', 'assignment_group_2202', 'assignment_2302', 'assignment_2304'
];
addDataAndInitialize();
gridSpecHelper.updateColumnOrder(customOrder);
gradebook.updateCurrentModule('2602');
gradebook.updateCurrentModule('0');
deepEqual(gridSpecHelper.listColumnIds(), customOrder);
});
});
});
'student',
'custom_col_2401',
'custom_col_2402',
'total_grade',
'assignment_group_2201',
'assignment_2301',
'assignment_2303',
'assignment_group_2202',
'assignment_2302',
'assignment_2304'
]
addDataAndInitialize()
gridSpecHelper.updateColumnOrder(customOrder)
gradebook.updateCurrentModule('2602')
gradebook.updateCurrentModule('0')
deepEqual(gridSpecHelper.listColumnIds(), customOrder)
})
})
})

View File

@ -16,8 +16,8 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import $ from 'jquery';
import fakeENV from 'helpers/fakeENV';
import $ from 'jquery'
import fakeENV from 'helpers/fakeENV'
import DataLoader from 'jsx/gradezilla/DataLoader'
import {
createGradebook,
@ -26,34 +26,35 @@ import {
import SlickGridSpecHelper from '../../gradezilla/default_gradebook/GradebookGrid/GridSupport/SlickGridSpecHelper'
QUnit.module('Gradebook Grid Column Ordering', function(suiteHooks) {
let $fixture;
let gridSpecHelper;
let gradebook;
let dataLoader;
let $fixture
let gridSpecHelper
let gradebook
let dataLoader
let assignmentGroups;
let assignments;
let contextModules;
let customColumns;
let assignmentGroups
let assignments
let contextModules
let customColumns
function createContextModules() {
contextModules = [
{id: '2601', position: 3, name: 'Final Module'},
{id: '2602', position: 2, name: 'Second Module'},
{id: '2603', position: 1, name: 'First Module'}
];
]
}
function createCustomColumns() {
customColumns = [
{id: '2401', teacher_notes: true, title: 'Notes'},
{id: '2402', teacher_notes: false, title: 'Other Notes'}
];
]
}
function createAssignments() {
assignments = {
homework: [{
homework: [
{
id: '2301',
assignment_group_id: '2201',
course_id: '1201',
@ -68,7 +69,8 @@ QUnit.module('Gradebook Grid Column Ordering', function (suiteHooks) {
position: 1,
published: true,
submission_types: ['online_text_entry']
}, {
},
{
id: '2303',
assignment_group_id: '2201',
course_id: '1201',
@ -83,9 +85,11 @@ QUnit.module('Gradebook Grid Column Ordering', function (suiteHooks) {
position: 2,
published: true,
submission_types: ['online_text_entry']
}],
}
],
quizzes: [{
quizzes: [
{
id: '2302',
assignment_group_id: '2202',
course_id: '1201',
@ -100,7 +104,8 @@ QUnit.module('Gradebook Grid Column Ordering', function (suiteHooks) {
position: 1,
published: true,
submission_types: ['online_quiz']
}, {
},
{
id: '2304',
assignment_group_id: '2202',
course_id: '1201',
@ -115,68 +120,69 @@ QUnit.module('Gradebook Grid Column Ordering', function (suiteHooks) {
position: 2,
published: true,
submission_types: ['online_quiz']
}]
};
}
]
}
}
function createAssignmentGroups() {
assignmentGroups = [
{id: '2201', position: 2, name: 'Homework', assignments: assignments.homework},
{id: '2202', position: 1, name: 'Quizzes', assignments: assignments.quizzes}
];
]
}
function addStudentIds() {
dataLoader.gotStudentIds.resolve({
user_ids: ['1101']
});
})
}
function addGradingPeriodAssignments() {
dataLoader.gotGradingPeriodAssignments.resolve({
grading_period_assignments: {1401: ['2301'], 1402: ['2302']}
});
})
}
function addContextModules() {
dataLoader.gotContextModules.resolve(contextModules);
dataLoader.gotContextModules.resolve(contextModules)
}
function addCustomColumns() {
dataLoader.gotCustomColumns.resolve(customColumns);
dataLoader.gotCustomColumns.resolve(customColumns)
}
function addAssignmentGroups() {
dataLoader.gotAssignmentGroups.resolve(assignmentGroups);
dataLoader.gotAssignmentGroups.resolve(assignmentGroups)
}
function addGridData() {
addStudentIds();
addContextModules();
addCustomColumns();
addAssignmentGroups();
addGradingPeriodAssignments();
addStudentIds()
addContextModules()
addCustomColumns()
addAssignmentGroups()
addGradingPeriodAssignments()
}
function arrangeColumnsBy(sortType, direction) {
gradebook.arrangeColumnsBy({ sortType, direction });
gradebook.arrangeColumnsBy({sortType, direction})
}
function createGradebookAndAddData(options) {
gradebook = createGradebook(options);
gradebook.initialize();
addGridData();
gridSpecHelper = new SlickGridSpecHelper(gradebook.gradebookGrid);
gradebook = createGradebook(options)
gradebook.initialize()
addGridData()
gridSpecHelper = new SlickGridSpecHelper(gradebook.gradebookGrid)
}
suiteHooks.beforeEach(function() {
$fixture = document.createElement('div');
document.body.appendChild($fixture);
setFixtureHtml($fixture);
$fixture = document.createElement('div')
document.body.appendChild($fixture)
setFixtureHtml($fixture)
fakeENV.setup({
current_user_id: '1101'
});
})
dataLoader = {
gotAssignmentGroups: $.Deferred(),
@ -187,272 +193,387 @@ QUnit.module('Gradebook Grid Column Ordering', function (suiteHooks) {
gotStudentIds: $.Deferred(),
gotStudents: $.Deferred(),
gotSubmissions: $.Deferred()
};
sinon.stub(DataLoader, 'loadGradebookData').returns(dataLoader);
sinon.stub(DataLoader, 'getDataForColumn');
}
sinon.stub(DataLoader, 'loadGradebookData').returns(dataLoader)
sinon.stub(DataLoader, 'getDataForColumn')
createAssignments();
createAssignmentGroups();
createContextModules();
createCustomColumns();
});
createAssignments()
createAssignmentGroups()
createContextModules()
createCustomColumns()
})
suiteHooks.afterEach(function() {
gradebook.destroy();
DataLoader.loadGradebookData.restore();
DataLoader.getDataForColumn.restore();
fakeENV.teardown();
$fixture.remove();
});
gradebook.destroy()
DataLoader.loadGradebookData.restore()
DataLoader.getDataForColumn.restore()
fakeENV.teardown()
$fixture.remove()
})
QUnit.module('when initializing the grid', function() {
test('defaults assignment column order to assignment group positions when setting is not set', function() {
createGradebookAndAddData();
createGradebookAndAddData()
const expectedOrder = [
'assignment_2302', 'assignment_2304', 'assignment_2301', 'assignment_2303',
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
});
'assignment_2302',
'assignment_2304',
'assignment_2301',
'assignment_2303',
'assignment_group_2202',
'assignment_group_2201',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
})
test('sorts assignment columns by assignment name when setting is "name"', function() {
createGradebookAndAddData({
gradebook_column_order_settings: {sortType: 'name', direction: 'ascending'}
});
})
const expectedOrder = [
'assignment_2303', 'assignment_2304', 'assignment_2301', 'assignment_2302',
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
});
'assignment_2303',
'assignment_2304',
'assignment_2301',
'assignment_2302',
'assignment_group_2202',
'assignment_group_2201',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
})
test('sorts assignment columns by assignment due date when setting is "due date"', function() {
createGradebookAndAddData({
gradebook_column_order_settings: {sortType: 'due_date', direction: 'ascending'}
});
})
const expectedOrder = [
'assignment_2301', 'assignment_2302', 'assignment_2304', 'assignment_2303',
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
});
'assignment_2301',
'assignment_2302',
'assignment_2304',
'assignment_2303',
'assignment_group_2202',
'assignment_group_2201',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
})
test('sorts assignment columns by assignment points possible when setting is "points"', function() {
createGradebookAndAddData({
gradebook_column_order_settings: {sortType: 'points', direction: 'ascending'}
});
})
const expectedOrder = [
'assignment_2301', 'assignment_2302', 'assignment_2303', 'assignment_2304',
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
});
'assignment_2301',
'assignment_2302',
'assignment_2303',
'assignment_2304',
'assignment_group_2202',
'assignment_group_2201',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
})
test('sorts assignment columns by module position when setting is "module position"', function() {
createGradebookAndAddData({
gradebook_column_order_settings: {sortType: 'module_position', direction: 'ascending'}
});
})
const expectedOrder = [
'assignment_2304', 'assignment_2302', 'assignment_2301', 'assignment_2303',
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
});
});
'assignment_2304',
'assignment_2302',
'assignment_2301',
'assignment_2303',
'assignment_group_2202',
'assignment_group_2201',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
})
})
QUnit.module('when sorting by default', function() {
test('sorts assignment columns by assignment group position', function() {
assignments.homework.splice(1, 1);
assignments.quizzes.splice(1, 1);
createGradebookAndAddData();
arrangeColumnsBy('default', 'ascending');
assignments.homework.splice(1, 1)
assignments.quizzes.splice(1, 1)
createGradebookAndAddData()
arrangeColumnsBy('default', 'ascending')
const expectedOrder = [
'assignment_2302', 'assignment_2301', 'assignment_group_2202', 'assignment_group_2201', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
});
'assignment_2302',
'assignment_2301',
'assignment_group_2202',
'assignment_group_2201',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
})
test('additionally sorts assignment columns by position within assignment groups', function() {
createGradebookAndAddData();
arrangeColumnsBy('default', 'ascending');
createGradebookAndAddData()
arrangeColumnsBy('default', 'ascending')
const expectedOrder = [
'assignment_2302', 'assignment_2304', 'assignment_2301', 'assignment_2303',
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
});
'assignment_2302',
'assignment_2304',
'assignment_2301',
'assignment_2303',
'assignment_group_2202',
'assignment_group_2201',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
})
test('optionally sorts in descending order', function() {
createGradebookAndAddData();
arrangeColumnsBy('default', 'descending');
createGradebookAndAddData()
arrangeColumnsBy('default', 'descending')
const expectedOrder = [
'assignment_2303', 'assignment_2301', 'assignment_2304', 'assignment_2302',
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
});
});
'assignment_2303',
'assignment_2301',
'assignment_2304',
'assignment_2302',
'assignment_group_2202',
'assignment_group_2201',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
})
})
QUnit.module('when sorting by name', function() {
test('sorts assignment columns by assignment name', function() {
createGradebookAndAddData();
arrangeColumnsBy('name', 'ascending');
createGradebookAndAddData()
arrangeColumnsBy('name', 'ascending')
const expectedOrder = [
'assignment_2303', 'assignment_2304', 'assignment_2301', 'assignment_2302',
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
});
'assignment_2303',
'assignment_2304',
'assignment_2301',
'assignment_2302',
'assignment_group_2202',
'assignment_group_2201',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
})
test('optionally sorts in descending order', function() {
createGradebookAndAddData();
arrangeColumnsBy('name', 'descending');
createGradebookAndAddData()
arrangeColumnsBy('name', 'descending')
const expectedOrder = [
'assignment_2302', 'assignment_2301', 'assignment_2304', 'assignment_2303',
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
});
});
'assignment_2302',
'assignment_2301',
'assignment_2304',
'assignment_2303',
'assignment_group_2202',
'assignment_group_2201',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
})
})
QUnit.module('when sorting by due date', function() {
test('sorts assignment columns by assignment due date', function() {
createGradebookAndAddData();
arrangeColumnsBy('due_date', 'ascending');
createGradebookAndAddData()
arrangeColumnsBy('due_date', 'ascending')
const expectedOrder = [
'assignment_2301', 'assignment_2302', 'assignment_2304', 'assignment_2303',
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
});
'assignment_2301',
'assignment_2302',
'assignment_2304',
'assignment_2303',
'assignment_group_2202',
'assignment_group_2201',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
})
test('sorts assignments with due dates before assignments without due dates', function() {
assignments.quizzes[0].due_at = null;
createGradebookAndAddData();
arrangeColumnsBy('due_date', 'ascending');
assignments.quizzes[0].due_at = null
createGradebookAndAddData()
arrangeColumnsBy('due_date', 'ascending')
const expectedOrder = [
'assignment_2301', 'assignment_2304', 'assignment_2303', 'assignment_2302',
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
});
'assignment_2301',
'assignment_2304',
'assignment_2303',
'assignment_2302',
'assignment_group_2202',
'assignment_group_2201',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
})
test('optionally sorts in descending order', function() {
createGradebookAndAddData();
arrangeColumnsBy('due_date', 'descending');
createGradebookAndAddData()
arrangeColumnsBy('due_date', 'descending')
const expectedOrder = [
'assignment_2303', 'assignment_2304', 'assignment_2302', 'assignment_2301',
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
});
});
'assignment_2303',
'assignment_2304',
'assignment_2302',
'assignment_2301',
'assignment_group_2202',
'assignment_group_2201',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
})
})
QUnit.module('when sorting by points', function() {
test('sorts assignment columns by assignment points possible', function() {
createGradebookAndAddData();
arrangeColumnsBy('points', 'ascending');
createGradebookAndAddData()
arrangeColumnsBy('points', 'ascending')
const expectedOrder = [
'assignment_2301', 'assignment_2302', 'assignment_2303', 'assignment_2304',
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
});
'assignment_2301',
'assignment_2302',
'assignment_2303',
'assignment_2304',
'assignment_group_2202',
'assignment_group_2201',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
})
test('optionally sorts in descending order', function() {
createGradebookAndAddData();
arrangeColumnsBy('points', 'descending');
createGradebookAndAddData()
arrangeColumnsBy('points', 'descending')
const expectedOrder = [
'assignment_2304', 'assignment_2303', 'assignment_2302', 'assignment_2301',
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
});
});
'assignment_2304',
'assignment_2303',
'assignment_2302',
'assignment_2301',
'assignment_group_2202',
'assignment_group_2201',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
})
})
QUnit.module('when sorting by module position', function() {
test('sorts assignment columns by module position', function() {
assignments.homework.splice(1, 1);
createGradebookAndAddData();
arrangeColumnsBy('module_position', 'ascending');
assignments.homework.splice(1, 1)
createGradebookAndAddData()
arrangeColumnsBy('module_position', 'ascending')
const expectedOrder = [
'assignment_2304', 'assignment_2302', 'assignment_2301',
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
});
'assignment_2304',
'assignment_2302',
'assignment_2301',
'assignment_group_2202',
'assignment_group_2201',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
})
test('additionally sorts assignment columns by position within modules', function() {
createGradebookAndAddData();
arrangeColumnsBy('module_position', 'ascending');
createGradebookAndAddData()
arrangeColumnsBy('module_position', 'ascending')
const expectedOrder = [
'assignment_2304', 'assignment_2302', 'assignment_2301', 'assignment_2303',
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
});
'assignment_2304',
'assignment_2302',
'assignment_2301',
'assignment_2303',
'assignment_group_2202',
'assignment_group_2201',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
})
test('sorts assignments with modules before assignments without modules', function() {
assignments.quizzes[0].module_ids = [];
assignments.quizzes[0].module_positions = [];
createGradebookAndAddData();
arrangeColumnsBy('module_position', 'ascending');
assignments.quizzes[0].module_ids = []
assignments.quizzes[0].module_positions = []
createGradebookAndAddData()
arrangeColumnsBy('module_position', 'ascending')
const expectedOrder = [
'assignment_2304', 'assignment_2301', 'assignment_2303', 'assignment_2302',
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
});
'assignment_2304',
'assignment_2301',
'assignment_2303',
'assignment_2302',
'assignment_group_2202',
'assignment_group_2201',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
})
test('optionally sorts in descending order', function() {
createGradebookAndAddData();
arrangeColumnsBy('module_position', 'descending');
createGradebookAndAddData()
arrangeColumnsBy('module_position', 'descending')
const expectedOrder = [
'assignment_2303', 'assignment_2301', 'assignment_2302', 'assignment_2304',
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
];
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
});
});
'assignment_2303',
'assignment_2301',
'assignment_2302',
'assignment_2304',
'assignment_group_2202',
'assignment_group_2201',
'total_grade'
]
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
})
})
QUnit.module('when using a custom order', function() {
test('sorts all saved columns in the saved order', function() {
const customOrder = [
'total_grade', 'assignment_group_2201', 'assignment_2301', 'assignment_2303',
'assignment_group_2202', 'assignment_2302', 'assignment_2304'
];
'total_grade',
'assignment_group_2201',
'assignment_2301',
'assignment_2303',
'assignment_group_2202',
'assignment_2302',
'assignment_2304'
]
createGradebookAndAddData({
gradebook_column_order_settings: {sortType: 'custom', customOrder}
});
deepEqual(gridSpecHelper.listScrollableColumnIds(), customOrder);
});
})
deepEqual(gridSpecHelper.listScrollableColumnIds(), customOrder)
})
test('sorts any unsaved columns after the saved order', function() {
const customOrder = [
'total_grade', 'assignment_2301', 'assignment_group_2202', 'assignment_2302', 'assignment_2304'
];
'total_grade',
'assignment_2301',
'assignment_group_2202',
'assignment_2302',
'assignment_2304'
]
createGradebookAndAddData({
gradebook_column_order_settings: {sortType: 'custom', customOrder}
});
})
const expectedOrder = [
'total_grade', 'assignment_2301', 'assignment_group_2202', 'assignment_2302',
'assignment_2304', 'assignment_2303', 'assignment_group_2201'
];
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
});
'total_grade',
'assignment_2301',
'assignment_group_2202',
'assignment_2302',
'assignment_2304',
'assignment_2303',
'assignment_group_2201'
]
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
})
test('sorts unsaved columns by assignment group position', function() {
const customOrder = [
'total_grade', 'assignment_2301', 'assignment_group_2202', 'assignment_group_2201'
];
'total_grade',
'assignment_2301',
'assignment_group_2202',
'assignment_group_2201'
]
createGradebookAndAddData({
gradebook_column_order_settings: {sortType: 'custom', customOrder}
});
})
const expectedOrder = [
'total_grade', 'assignment_2301', 'assignment_group_2202', 'assignment_group_2201',
'assignment_2302', 'assignment_2304', 'assignment_2303'
];
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
});
});
});
'total_grade',
'assignment_2301',
'assignment_group_2202',
'assignment_group_2201',
'assignment_2302',
'assignment_2304',
'assignment_2303'
]
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
})
})
})

View File

@ -16,8 +16,8 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import $ from 'jquery';
import fakeENV from 'helpers/fakeENV';
import $ from 'jquery'
import fakeENV from 'helpers/fakeENV'
import DataLoader from 'jsx/gradezilla/DataLoader'
import {
createGradebook,
@ -25,35 +25,36 @@ import {
} from 'jsx/gradezilla/default_gradebook/__tests__/GradebookSpecHelper'
import SlickGridSpecHelper from '../../gradezilla/default_gradebook/GradebookGrid/GridSupport/SlickGridSpecHelper'
QUnit.module('Gradebook Grid Column Widths', (suiteHooks) => {
let $fixture;
let gridSpecHelper;
let gradebook;
let dataLoader;
QUnit.module('Gradebook Grid Column Widths', suiteHooks => {
let $fixture
let gridSpecHelper
let gradebook
let dataLoader
let assignmentGroups;
let assignments;
let contextModules;
let customColumns;
let assignmentGroups
let assignments
let contextModules
let customColumns
function createContextModules() {
contextModules = [
{id: '2601', position: 3, name: 'Final Module'},
{id: '2602', position: 2, name: 'Second Module'},
{id: '2603', position: 1, name: 'First Module'}
];
]
}
function createCustomColumns() {
customColumns = [
{id: '2401', teacher_notes: true, title: 'Notes'},
{id: '2402', teacher_notes: false, title: 'Other Notes'}
];
]
}
function createAssignments() {
assignments = {
homework: [{
homework: [
{
id: '2301',
assignment_group_id: '2201',
course_id: '1201',
@ -68,7 +69,8 @@ QUnit.module('Gradebook Grid Column Widths', (suiteHooks) => {
position: 1,
published: true,
submission_types: ['online_text_entry']
}, {
},
{
id: '2303',
assignment_group_id: '2201',
course_id: '1201',
@ -83,9 +85,11 @@ QUnit.module('Gradebook Grid Column Widths', (suiteHooks) => {
position: 2,
published: true,
submission_types: ['online_text_entry']
}],
}
],
quizzes: [{
quizzes: [
{
id: '2302',
assignment_group_id: '2202',
course_id: '1201',
@ -100,7 +104,8 @@ QUnit.module('Gradebook Grid Column Widths', (suiteHooks) => {
position: 1,
published: true,
submission_types: ['online_quiz']
}, {
},
{
id: '2304',
assignment_group_id: '2202',
course_id: '1201',
@ -115,64 +120,65 @@ QUnit.module('Gradebook Grid Column Widths', (suiteHooks) => {
position: 2,
published: true,
submission_types: ['online_quiz']
}]
};
}
]
}
}
function createAssignmentGroups() {
assignmentGroups = [
{id: '2201', position: 2, name: 'Homework', assignments: assignments.homework},
{id: '2202', position: 1, name: 'Quizzes', assignments: assignments.quizzes}
];
]
}
function addStudentIds() {
dataLoader.gotStudentIds.resolve({
user_ids: ['1101']
});
})
}
function addGradingPeriodAssignments() {
dataLoader.gotGradingPeriodAssignments.resolve({
grading_period_assignments: {1401: ['2301'], 1402: ['2302']}
});
})
}
function addContextModules() {
dataLoader.gotContextModules.resolve(contextModules);
dataLoader.gotContextModules.resolve(contextModules)
}
function addCustomColumns() {
dataLoader.gotCustomColumns.resolve(customColumns);
dataLoader.gotCustomColumns.resolve(customColumns)
}
function addAssignmentGroups() {
dataLoader.gotAssignmentGroups.resolve(assignmentGroups);
dataLoader.gotAssignmentGroups.resolve(assignmentGroups)
}
function addGridData() {
addStudentIds();
addContextModules();
addCustomColumns();
addAssignmentGroups();
addGradingPeriodAssignments();
addStudentIds()
addContextModules()
addCustomColumns()
addAssignmentGroups()
addGradingPeriodAssignments()
}
function createGradebookAndAddData(options) {
gradebook = createGradebook(options);
gradebook.initialize();
addGridData();
gridSpecHelper = new SlickGridSpecHelper(gradebook.gradebookGrid);
gradebook = createGradebook(options)
gradebook.initialize()
addGridData()
gridSpecHelper = new SlickGridSpecHelper(gradebook.gradebookGrid)
}
suiteHooks.beforeEach(() => {
$fixture = document.createElement('div');
document.body.appendChild($fixture);
setFixtureHtml($fixture);
$fixture = document.createElement('div')
document.body.appendChild($fixture)
setFixtureHtml($fixture)
fakeENV.setup({
current_user_id: '1101'
});
})
dataLoader = {
gotAssignmentGroups: $.Deferred(),
@ -183,100 +189,103 @@ QUnit.module('Gradebook Grid Column Widths', (suiteHooks) => {
gotStudentIds: $.Deferred(),
gotStudents: $.Deferred(),
gotSubmissions: $.Deferred()
};
sinon.stub(DataLoader, 'loadGradebookData').returns(dataLoader);
sinon.stub(DataLoader, 'getDataForColumn');
}
sinon.stub(DataLoader, 'loadGradebookData').returns(dataLoader)
sinon.stub(DataLoader, 'getDataForColumn')
createAssignments();
createAssignmentGroups();
createContextModules();
createCustomColumns();
});
createAssignments()
createAssignmentGroups()
createContextModules()
createCustomColumns()
})
suiteHooks.afterEach(() => {
gradebook.gradebookGrid.destroy();
$(document).unbind('gridready');
DataLoader.loadGradebookData.restore();
DataLoader.getDataForColumn.restore();
fakeENV.teardown();
$fixture.remove();
});
gradebook.gradebookGrid.destroy()
$(document).unbind('gridready')
DataLoader.loadGradebookData.restore()
DataLoader.getDataForColumn.restore()
fakeENV.teardown()
$fixture.remove()
})
QUnit.module('when initializing the grid', (hooks) => {
QUnit.module('when initializing the grid', hooks => {
hooks.beforeEach(() => {
gradebook = createGradebook();
gradebook.gradebookColumnSizeSettings = { assignment_2302: 10, assignment_2303: 54 };
gradebook.initialize();
addGridData();
gridSpecHelper = new SlickGridSpecHelper(gradebook.gradebookGrid);
});
gradebook = createGradebook()
gradebook.gradebookColumnSizeSettings = {assignment_2302: 10, assignment_2303: 54}
gradebook.initialize()
addGridData()
gridSpecHelper = new SlickGridSpecHelper(gradebook.gradebookGrid)
})
test('defaults assignment column size to fit the assignment name', () => {
const columnNode = gridSpecHelper.getColumnHeaderNode('assignment_2301');
ok(columnNode.offsetWidth > 10, 'width is not the minimum');
});
const columnNode = gridSpecHelper.getColumnHeaderNode('assignment_2301')
ok(columnNode.offsetWidth > 10, 'width is not the minimum')
})
test('uses a stored width for assignment column headers', () => {
const columnNode = gridSpecHelper.getColumnHeaderNode('assignment_2303');
strictEqual(columnNode.offsetWidth, 54);
});
const columnNode = gridSpecHelper.getColumnHeaderNode('assignment_2303')
strictEqual(columnNode.offsetWidth, 54)
})
test('hides assignment column header content when the column is minimized', () => {
const columnNode = gridSpecHelper.getColumnHeaderNode('assignment_2302');
ok(columnNode.classList.contains('minimized'));
});
const columnNode = gridSpecHelper.getColumnHeaderNode('assignment_2302')
ok(columnNode.classList.contains('minimized'))
})
test('hides assignment column cell content when the column is minimized', () => {
const columnIndex = gridSpecHelper.listColumnIds().indexOf('assignment_2302');
const cellNode = gradebook.gradebookGrid.grid.getCellNode(0, columnIndex);
ok(cellNode.classList.contains('minimized'));
});
});
const columnIndex = gridSpecHelper.listColumnIds().indexOf('assignment_2302')
const cellNode = gradebook.gradebookGrid.grid.getCellNode(0, columnIndex)
ok(cellNode.classList.contains('minimized'))
})
})
QUnit.module('onColumnsResized', (hooks) => {
QUnit.module('onColumnsResized', hooks => {
function resizeColumn(columnId, widthChange) {
const column = gridSpecHelper.getColumn(columnId);
const updatedColumn = { ...column, width: column.width + widthChange };
gradebook.gradebookGrid.gridSupport.events.onColumnsResized.trigger(null, [updatedColumn]);
const column = gridSpecHelper.getColumn(columnId)
const updatedColumn = {...column, width: column.width + widthChange}
gradebook.gradebookGrid.gridSupport.events.onColumnsResized.trigger(null, [updatedColumn])
}
hooks.beforeEach(() => {
createGradebookAndAddData();
sinon.stub(gradebook, 'saveColumnWidthPreference');
});
createGradebookAndAddData()
sinon.stub(gradebook, 'saveColumnWidthPreference')
})
test('updates the column definitions for resized columns', () => {
const originalWidth = gridSpecHelper.getColumn('assignment_2304').width;
resizeColumn('assignment_2304', -20);
strictEqual(gradebook.gradebookGrid.gridData.columns.definitions.assignment_2304.width, originalWidth - 20);
});
const originalWidth = gridSpecHelper.getColumn('assignment_2304').width
resizeColumn('assignment_2304', -20)
strictEqual(
gradebook.gradebookGrid.gridData.columns.definitions.assignment_2304.width,
originalWidth - 20
)
})
test('hides assignment column header content when the column is minimized', () => {
resizeColumn('assignment_2304', -100);
const columnNode = gridSpecHelper.getColumnHeaderNode('assignment_2304');
ok(columnNode.classList.contains('minimized'));
});
resizeColumn('assignment_2304', -100)
const columnNode = gridSpecHelper.getColumnHeaderNode('assignment_2304')
ok(columnNode.classList.contains('minimized'))
})
test('hides assignment column cell content when the column is minimized', () => {
resizeColumn('assignment_2304', -100);
const columnIndex = gridSpecHelper.listColumnIds().indexOf('assignment_2304');
const cellNode = gradebook.gradebookGrid.grid.getCellNode(0, columnIndex);
ok(cellNode.classList.contains('minimized'));
});
resizeColumn('assignment_2304', -100)
const columnIndex = gridSpecHelper.listColumnIds().indexOf('assignment_2304')
const cellNode = gradebook.gradebookGrid.grid.getCellNode(0, columnIndex)
ok(cellNode.classList.contains('minimized'))
})
test('unhides assignment column header content when the column is unminimized', () => {
resizeColumn('assignment_2304', -100);
resizeColumn('assignment_2304', 1);
const columnNode = gridSpecHelper.getColumnHeaderNode('assignment_2304');
notOk(columnNode.classList.contains('minimized'));
});
resizeColumn('assignment_2304', -100)
resizeColumn('assignment_2304', 1)
const columnNode = gridSpecHelper.getColumnHeaderNode('assignment_2304')
notOk(columnNode.classList.contains('minimized'))
})
test('unhides assignment column cell content when the column is unminimized', () => {
resizeColumn('assignment_2304', -100);
resizeColumn('assignment_2304', 1);
const columnIndex = gridSpecHelper.listColumnIds().indexOf('assignment_2304');
const cellNode = gradebook.gradebookGrid.grid.getCellNode(0, columnIndex);
notOk(cellNode.classList.contains('minimized'));
});
});
});
resizeColumn('assignment_2304', -100)
resizeColumn('assignment_2304', 1)
const columnIndex = gridSpecHelper.listColumnIds().indexOf('assignment_2304')
const cellNode = gradebook.gradebookGrid.grid.getCellNode(0, columnIndex)
notOk(cellNode.classList.contains('minimized'))
})
})
})

View File

@ -16,172 +16,199 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import _ from 'underscore';
import GradebookApi from 'jsx/gradezilla/default_gradebook/apis/GradebookApi';
import _ from 'underscore'
import GradebookApi from 'jsx/gradezilla/default_gradebook/apis/GradebookApi'
QUnit.module('GradebookApi.createTeacherNotesColumn', {
setup() {
this.customColumn = { id: '2401', hidden: false, position: 1, teacher_notes: true, title: 'Notes' };
this.createTeacherNotesColumnUrl = '/api/v1/courses/1201/custom_gradebook_columns';
this.server = sinon.fakeServer.create({ respondImmediately: true });
const responseBody = JSON.stringify(this.customColumn);
this.server.respondWith('POST', this.createTeacherNotesColumnUrl, [200, { 'Content-Type': 'application/json' }, responseBody]);
this.customColumn = {
id: '2401',
hidden: false,
position: 1,
teacher_notes: true,
title: 'Notes'
}
this.createTeacherNotesColumnUrl = '/api/v1/courses/1201/custom_gradebook_columns'
this.server = sinon.fakeServer.create({respondImmediately: true})
const responseBody = JSON.stringify(this.customColumn)
this.server.respondWith('POST', this.createTeacherNotesColumnUrl, [
200,
{'Content-Type': 'application/json'},
responseBody
])
},
getRequest() {
// filter requests to eliminate spec pollution from unrelated specs
return _.find(this.server.requests, request => request.url.includes(this.createTeacherNotesColumnUrl));
return _.find(this.server.requests, request =>
request.url.includes(this.createTeacherNotesColumnUrl)
)
},
teardown() {
this.server.restore();
this.server.restore()
}
});
})
test('sends a post request to the "create teacher notes column" url', function() {
return GradebookApi.createTeacherNotesColumn('1201')
.then(() => {
const request = this.getRequest();
equal(request.method, 'POST');
equal(request.url, this.createTeacherNotesColumnUrl);
});
});
return GradebookApi.createTeacherNotesColumn('1201').then(() => {
const request = this.getRequest()
equal(request.method, 'POST')
equal(request.url, this.createTeacherNotesColumnUrl)
})
})
test('includes data to create a teacher notes column', function() {
return GradebookApi.createTeacherNotesColumn('1201')
.then(() => {
const bodyData = JSON.parse(this.getRequest().requestBody);
equal(bodyData.column.title, 'Notes');
strictEqual(bodyData.column.position, 1);
equal(bodyData.column.teacher_notes, true);
});
});
return GradebookApi.createTeacherNotesColumn('1201').then(() => {
const bodyData = JSON.parse(this.getRequest().requestBody)
equal(bodyData.column.title, 'Notes')
strictEqual(bodyData.column.position, 1)
equal(bodyData.column.teacher_notes, true)
})
})
test('includes required request headers', function() {
return GradebookApi.createTeacherNotesColumn('1201')
.then(() => {
const { requestHeaders } = this.getRequest();
ok(requestHeaders.Accept.includes('application/json+canvas-string-ids'), 'includes header for Canvas string ids');
ok(requestHeaders['Content-Type'].includes('application/json'),
'includes "application/json" content type');
equal(requestHeaders['X-Requested-With'], 'XMLHttpRequest');
});
});
return GradebookApi.createTeacherNotesColumn('1201').then(() => {
const {requestHeaders} = this.getRequest()
ok(
requestHeaders.Accept.includes('application/json+canvas-string-ids'),
'includes header for Canvas string ids'
)
ok(
requestHeaders['Content-Type'].includes('application/json'),
'includes "application/json" content type'
)
equal(requestHeaders['X-Requested-With'], 'XMLHttpRequest')
})
})
test('sends the column data to the success handler', function() {
return GradebookApi.createTeacherNotesColumn('1201')
.then(({ data }) => {
deepEqual(data, this.customColumn);
});
});
return GradebookApi.createTeacherNotesColumn('1201').then(({data}) => {
deepEqual(data, this.customColumn)
})
})
QUnit.module('GradebookApi.updateTeacherNotesColumn', {
setup() {
this.customColumn = { id: '2401', hidden: true, position: 1, teacher_notes: true, title: 'Notes' };
this.updateTeacherNotesColumnUrl = '/api/v1/courses/1201/custom_gradebook_columns/2401';
this.server = sinon.fakeServer.create({ respondImmediately: true });
const responseBody = JSON.stringify(this.customColumn);
this.server.respondWith('PUT', this.updateTeacherNotesColumnUrl, [200, { 'Content-Type': 'application/json' }, responseBody]);
this.customColumn = {id: '2401', hidden: true, position: 1, teacher_notes: true, title: 'Notes'}
this.updateTeacherNotesColumnUrl = '/api/v1/courses/1201/custom_gradebook_columns/2401'
this.server = sinon.fakeServer.create({respondImmediately: true})
const responseBody = JSON.stringify(this.customColumn)
this.server.respondWith('PUT', this.updateTeacherNotesColumnUrl, [
200,
{'Content-Type': 'application/json'},
responseBody
])
},
getRequest() {
// filter requests to eliminate spec pollution from unrelated specs
return _.find(this.server.requests, request => request.url.includes(this.updateTeacherNotesColumnUrl));
return _.find(this.server.requests, request =>
request.url.includes(this.updateTeacherNotesColumnUrl)
)
},
teardown() {
this.server.restore();
this.server.restore()
}
});
})
test('sends a post request to the "create teacher notes column" url', function() {
return GradebookApi.updateTeacherNotesColumn('1201', '2401', { hidden: true })
.then(() => {
const request = this.getRequest();
equal(request.method, 'PUT');
equal(request.url, this.updateTeacherNotesColumnUrl);
});
});
return GradebookApi.updateTeacherNotesColumn('1201', '2401', {hidden: true}).then(() => {
const request = this.getRequest()
equal(request.method, 'PUT')
equal(request.url, this.updateTeacherNotesColumnUrl)
})
})
test('includes params for updating a teacher notes column', function() {
return GradebookApi.updateTeacherNotesColumn('1201', '2401', { hidden: true })
.then(() => {
const bodyData = JSON.parse(this.getRequest().requestBody);
equal(bodyData.column.hidden, true);
});
});
return GradebookApi.updateTeacherNotesColumn('1201', '2401', {hidden: true}).then(() => {
const bodyData = JSON.parse(this.getRequest().requestBody)
equal(bodyData.column.hidden, true)
})
})
test('includes required request headers', function() {
return GradebookApi.updateTeacherNotesColumn('1201', '2401', { hidden: true })
.then(() => {
const { requestHeaders } = this.getRequest();
ok(requestHeaders.Accept.includes('application/json+canvas-string-ids'), 'includes header for Canvas string ids');
ok(requestHeaders['Content-Type'].includes('application/json'),
'includes "application/json" content type');
equal(requestHeaders['X-Requested-With'], 'XMLHttpRequest');
});
});
return GradebookApi.updateTeacherNotesColumn('1201', '2401', {hidden: true}).then(() => {
const {requestHeaders} = this.getRequest()
ok(
requestHeaders.Accept.includes('application/json+canvas-string-ids'),
'includes header for Canvas string ids'
)
ok(
requestHeaders['Content-Type'].includes('application/json'),
'includes "application/json" content type'
)
equal(requestHeaders['X-Requested-With'], 'XMLHttpRequest')
})
})
test('sends the column data to the success handler', function() {
return GradebookApi.updateTeacherNotesColumn('1201', '2401', { hidden: true })
.then(({ data }) => {
deepEqual(data, this.customColumn);
});
});
return GradebookApi.updateTeacherNotesColumn('1201', '2401', {hidden: true}).then(({data}) => {
deepEqual(data, this.customColumn)
})
})
QUnit.module('GradebookApi.updateSubmission', function(hooks) {
const courseId = '1201';
const assignmentId = '303';
const userId = '201';
const updateSubmissionUrl = `/api/v1/courses/${courseId}/assignments/${assignmentId}/submissions/${userId}`;
const submissionData = { all_submissions: [{ id: 301, late_policy_status: 'none' }] };
let server;
const courseId = '1201'
const assignmentId = '303'
const userId = '201'
const updateSubmissionUrl = `/api/v1/courses/${courseId}/assignments/${assignmentId}/submissions/${userId}`
const submissionData = {all_submissions: [{id: 301, late_policy_status: 'none'}]}
let server
hooks.beforeEach(function() {
server = sinon.fakeServer.create({ respondImmediately: true });
const responseBody = JSON.stringify(submissionData);
server.respondWith('PUT', updateSubmissionUrl, [200, { 'Content-Type': 'application/json' }, responseBody]);
});
server = sinon.fakeServer.create({respondImmediately: true})
const responseBody = JSON.stringify(submissionData)
server.respondWith('PUT', updateSubmissionUrl, [
200,
{'Content-Type': 'application/json'},
responseBody
])
})
hooks.afterEach(function() {
server.restore();
});
server.restore()
})
function getRequest() {
// filter requests to eliminate spec pollution from unrelated specs
return _.find(server.requests, request => request.url.includes(updateSubmissionUrl));
return _.find(server.requests, request => request.url.includes(updateSubmissionUrl))
}
test('sends a put request to the "update submission" url', function() {
return GradebookApi.updateSubmission(courseId, assignmentId, userId, { latePolicyStatus: 'none' })
.then(() => {
const request = getRequest();
strictEqual(request.method, 'PUT');
strictEqual(request.url, updateSubmissionUrl);
});
});
return GradebookApi.updateSubmission(courseId, assignmentId, userId, {
latePolicyStatus: 'none'
}).then(() => {
const request = getRequest()
strictEqual(request.method, 'PUT')
strictEqual(request.url, updateSubmissionUrl)
})
})
test('includes params for updating a submission', function() {
return GradebookApi.updateSubmission(courseId, assignmentId, userId, { latePolicyStatus: 'none' })
.then(() => {
const bodyData = JSON.parse(getRequest().requestBody);
deepEqual(bodyData.submission.late_policy_status, 'none');
});
});
return GradebookApi.updateSubmission(courseId, assignmentId, userId, {
latePolicyStatus: 'none'
}).then(() => {
const bodyData = JSON.parse(getRequest().requestBody)
deepEqual(bodyData.submission.late_policy_status, 'none')
})
})
test('includes params to request visibility for the submission', function() {
return GradebookApi.updateSubmission(courseId, assignmentId, userId, { latePolicyStatus: 'none' })
.then(() => {
const bodyData = JSON.parse(getRequest().requestBody);
strictEqual(bodyData.include.includes('visibility'), true);
});
});
return GradebookApi.updateSubmission(courseId, assignmentId, userId, {
latePolicyStatus: 'none'
}).then(() => {
const bodyData = JSON.parse(getRequest().requestBody)
strictEqual(bodyData.include.includes('visibility'), true)
})
})
test('sends the column data to the success handler', function() {
return GradebookApi.updateSubmission(courseId, assignmentId, userId, { latePolicyStatus: 'none' })
.then(({ data }) => {
deepEqual(data, submissionData);
});
});
});
return GradebookApi.updateSubmission(courseId, assignmentId, userId, {
latePolicyStatus: 'none'
}).then(({data}) => {
deepEqual(data, submissionData)
})
})
})

View File

@ -16,14 +16,14 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import _ from 'underscore';
import _ from 'underscore'
import {
DEFAULT_LATE_POLICY_DATA,
fetchLatePolicy,
createLatePolicy,
updateLatePolicy
} from 'jsx/gradezilla/default_gradebook/apis/GradebookSettingsModalApi';
import { underscore } from 'convert_case';
} from 'jsx/gradezilla/default_gradebook/apis/GradebookSettingsModalApi'
import {underscore} from 'convert_case'
const latePolicyData = {
id: '15',
@ -34,128 +34,138 @@ const latePolicyData = {
lateSubmissionInterval: 'day',
lateSubmissionMinimumPercentEnabled: true,
lateSubmissionMinimumPercent: 40.0
};
}
function getRequestWithUrl(server, url) {
// filter requests to eliminate spec pollution from unrelated specs
return _.find(server.requests, request => request.url.includes(url));
return _.find(server.requests, request => request.url.includes(url))
}
QUnit.module('GradebookSettingsModalApi.fetchLatePolicy success', {
setup() {
this.url = '/api/v1/courses/19/late_policy';
this.server = sinon.fakeServer.create({ respondImmediately: true });
const responseBody = JSON.stringify({ late_policy: underscore(latePolicyData) });
this.server.respondWith('GET', this.url, [200, { 'Content-Type': 'application/json' }, responseBody]);
this.url = '/api/v1/courses/19/late_policy'
this.server = sinon.fakeServer.create({respondImmediately: true})
const responseBody = JSON.stringify({late_policy: underscore(latePolicyData)})
this.server.respondWith('GET', this.url, [
200,
{'Content-Type': 'application/json'},
responseBody
])
},
teardown() {
this.server.restore();
this.server.restore()
}
});
})
test('returns the late policy', function() {
return fetchLatePolicy('19')
.then(({ data }) => {
deepEqual(data, { latePolicy: latePolicyData });
});
});
return fetchLatePolicy('19').then(({data}) => {
deepEqual(data, {latePolicy: latePolicyData})
})
})
QUnit.module('GradebookSettingsModalApi.fetchLatePolicy when late policy does not exist', {
setup() {
this.url = '/api/v1/courses/19/late_policy';
this.server = sinon.fakeServer.create({ respondImmediately: true });
const responseBody = JSON.stringify(
{ errors: [{ message: 'The specified resource does not exist.' }], error_report_id: '2199' }
);
this.server.respondWith('GET', this.url, [404, { 'Content-Type': 'application/json' }, responseBody]);
this.url = '/api/v1/courses/19/late_policy'
this.server = sinon.fakeServer.create({respondImmediately: true})
const responseBody = JSON.stringify({
errors: [{message: 'The specified resource does not exist.'}],
error_report_id: '2199'
})
this.server.respondWith('GET', this.url, [
404,
{'Content-Type': 'application/json'},
responseBody
])
},
teardown() {
this.server.restore();
this.server.restore()
}
});
})
test('returns default late policy data when the response is a 404', function() {
return fetchLatePolicy('19')
.then(({ data }) => {
deepEqual(data, { latePolicy: DEFAULT_LATE_POLICY_DATA });
});
});
return fetchLatePolicy('19').then(({data}) => {
deepEqual(data, {latePolicy: DEFAULT_LATE_POLICY_DATA})
})
})
QUnit.module('GradebookSettingsModalApi.fetchLatePolicy when the request fails', {
setup() {
this.url = '/api/v1/courses/19/late_policy';
this.server = sinon.fakeServer.create({ respondImmediately: true });
this.server.respondWith('GET', this.url, [500, { 'Content-Type': 'application/json' }, JSON.stringify({})]);
this.url = '/api/v1/courses/19/late_policy'
this.server = sinon.fakeServer.create({respondImmediately: true})
this.server.respondWith('GET', this.url, [
500,
{'Content-Type': 'application/json'},
JSON.stringify({})
])
},
teardown() {
this.server.restore();
this.server.restore()
}
});
})
test('rejects the promise when the response is not a 200 or a 404', function() {
return fetchLatePolicy('19')
.catch((error) => {
strictEqual(error.response.status, 500);
});
});
return fetchLatePolicy('19').catch(error => {
strictEqual(error.response.status, 500)
})
})
QUnit.module('GradebookSettingsModalApi.createLatePolicy', {
setup() {
this.latePolicyCreationData = { ...latePolicyData };
delete this.latePolicyCreationData.id;
this.url = '/api/v1/courses/19/late_policy';
this.server = sinon.fakeServer.create({ respondImmediately: true });
const responseBody = JSON.stringify({ late_policy: underscore(latePolicyData) });
this.server.respondWith('POST', this.url, [200, { 'Content-Type': 'application/json' }, responseBody]);
this.latePolicyCreationData = {...latePolicyData}
delete this.latePolicyCreationData.id
this.url = '/api/v1/courses/19/late_policy'
this.server = sinon.fakeServer.create({respondImmediately: true})
const responseBody = JSON.stringify({late_policy: underscore(latePolicyData)})
this.server.respondWith('POST', this.url, [
200,
{'Content-Type': 'application/json'},
responseBody
])
},
teardown() {
this.server.restore();
this.server.restore()
}
});
})
test('includes data to create a late_policy', function() {
return createLatePolicy('19', latePolicyData)
.then(() => {
const bodyData = JSON.parse(getRequestWithUrl(this.server, this.url).requestBody);
deepEqual(bodyData, { late_policy: underscore(latePolicyData) });
});
});
return createLatePolicy('19', latePolicyData).then(() => {
const bodyData = JSON.parse(getRequestWithUrl(this.server, this.url).requestBody)
deepEqual(bodyData, {late_policy: underscore(latePolicyData)})
})
})
test('returns the late policy', function() {
return createLatePolicy('19', this.latePolicyCreationData)
.then(({ data }) => {
deepEqual(data, { latePolicy: latePolicyData });
});
});
return createLatePolicy('19', this.latePolicyCreationData).then(({data}) => {
deepEqual(data, {latePolicy: latePolicyData})
})
})
QUnit.module('GradebookSettingsModalApi.updateLatePolicy', {
setup() {
this.url = '/api/v1/courses/19/late_policy';
this.changes = { lateSubmissionInterval: 'hour' };
this.server = sinon.fakeServer.create({ respondImmediately: true });
this.server.respondWith('PATCH', this.url, [204, {}, '']);
this.url = '/api/v1/courses/19/late_policy'
this.changes = {lateSubmissionInterval: 'hour'}
this.server = sinon.fakeServer.create({respondImmediately: true})
this.server.respondWith('PATCH', this.url, [204, {}, ''])
},
teardown() {
this.server.restore();
this.server.restore()
}
});
})
test('includes data to update a late_policy', function() {
return updateLatePolicy('19', this.changes)
.then(() => {
const bodyData = JSON.parse(getRequestWithUrl(this.server, this.url).requestBody);
deepEqual(bodyData, { late_policy: underscore(this.changes) });
});
});
return updateLatePolicy('19', this.changes).then(() => {
const bodyData = JSON.parse(getRequestWithUrl(this.server, this.url).requestBody)
deepEqual(bodyData, {late_policy: underscore(this.changes)})
})
})
test('returns a 204 (successfully fulfilled request and no content)', function() {
return updateLatePolicy('19', this.changes)
.then(({ status }) => {
equal(status, 204);
});
});
return updateLatePolicy('19', this.changes).then(({status}) => {
equal(status, 204)
})
})

View File

@ -16,49 +16,49 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { updateSubmissionComment } from 'jsx/gradezilla/default_gradebook/apis/SubmissionCommentApi';
import { underscore } from 'convert_case';
import {updateSubmissionComment} from 'jsx/gradezilla/default_gradebook/apis/SubmissionCommentApi'
import {underscore} from 'convert_case'
QUnit.module('SubmissionCommentApi.updateSubmissionComment', function(hooks) {
let server;
const commentId = '12';
const url = `/submission_comments/${commentId}`;
const updatedComment = 'an updated comment!';
const editedAt = '2015-10-12T19:25:41Z';
let server
const commentId = '12'
const url = `/submission_comments/${commentId}`
const updatedComment = 'an updated comment!'
const editedAt = '2015-10-12T19:25:41Z'
const submissionComment = {
id: commentId,
created_at: '2015-10-09T19:25:41Z',
comment: updatedComment,
edited_at: editedAt
};
const responseBody = JSON.stringify({ submission_comment: underscore(submissionComment) });
}
const responseBody = JSON.stringify({submission_comment: underscore(submissionComment)})
hooks.beforeEach(function() {
server = sinon.fakeServer.create({ respondImmediately: true });
});
server = sinon.fakeServer.create({respondImmediately: true})
})
hooks.afterEach(function() {
server.restore();
});
server.restore()
})
test('on success, returns the submission comment with the updated comment', function() {
server.respondWith('PUT', url, [200, { 'Content-Type': 'application/json' }, responseBody]);
return updateSubmissionComment(commentId, updatedComment).then((response) => {
strictEqual(response.data.comment, updatedComment);
});
});
server.respondWith('PUT', url, [200, {'Content-Type': 'application/json'}, responseBody])
return updateSubmissionComment(commentId, updatedComment).then(response => {
strictEqual(response.data.comment, updatedComment)
})
})
test('on success, returns the submission comment with an updated editedAt', function() {
server.respondWith('PUT', url, [200, { 'Content-Type': 'application/json' }, responseBody]);
return updateSubmissionComment(commentId, updatedComment).then((response) => {
strictEqual(response.data.editedAt.getTime(), new Date(editedAt).getTime());
});
});
server.respondWith('PUT', url, [200, {'Content-Type': 'application/json'}, responseBody])
return updateSubmissionComment(commentId, updatedComment).then(response => {
strictEqual(response.data.editedAt.getTime(), new Date(editedAt).getTime())
})
})
test('on failure, returns a rejected promise with the error', function() {
server.respondWith('PUT', url, [500, { 'Content-Type': 'application/json' }, JSON.stringify({})]);
return updateSubmissionComment(commentId, updatedComment).catch((error) => {
strictEqual(error.response.status, 500);
});
});
});
server.respondWith('PUT', url, [500, {'Content-Type': 'application/json'}, JSON.stringify({})])
return updateSubmissionComment(commentId, updatedComment).catch(error => {
strictEqual(error.response.status, 500)
})
})
})

View File

@ -17,7 +17,10 @@
*/
import DataLoader from 'jsx/gradezilla/DataLoader'
import {createGradebook, setFixtureHtml} from 'jsx/gradezilla/default_gradebook/__tests__/GradebookSpecHelper'
import {
createGradebook,
setFixtureHtml
} from 'jsx/gradezilla/default_gradebook/__tests__/GradebookSpecHelper'
import {createExampleStudents} from './DataLoadingSpecHelpers'
import DataLoadingWrapper from './DataLoadingWrapper'

View File

@ -17,7 +17,10 @@
*/
import DataLoader from 'jsx/gradezilla/DataLoader'
import {createGradebook, setFixtureHtml} from 'jsx/gradezilla/default_gradebook/__tests__/GradebookSpecHelper'
import {
createGradebook,
setFixtureHtml
} from 'jsx/gradezilla/default_gradebook/__tests__/GradebookSpecHelper'
import {createExampleStudents} from './DataLoadingSpecHelpers'
import DataLoadingWrapper from './DataLoadingWrapper'

View File

@ -17,7 +17,10 @@
*/
import DataLoader from 'jsx/gradezilla/DataLoader'
import {createGradebook, setFixtureHtml} from 'jsx/gradezilla/default_gradebook/__tests__/GradebookSpecHelper'
import {
createGradebook,
setFixtureHtml
} from 'jsx/gradezilla/default_gradebook/__tests__/GradebookSpecHelper'
import {createExampleStudents} from './DataLoadingSpecHelpers'
import DataLoadingWrapper from './DataLoadingWrapper'

View File

@ -16,94 +16,96 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import _ from 'lodash';
import StudentDatastore from 'jsx/gradezilla/default_gradebook/stores/StudentDatastore';
import _ from 'lodash'
import StudentDatastore from 'jsx/gradezilla/default_gradebook/stores/StudentDatastore'
QUnit.module('StudentDatastore', function(hooks) {
let studentDatastore;
let userStudentMap;
let testStudentMap;
let studentDatastore
let userStudentMap
let testStudentMap
hooks.beforeEach(function() {
userStudentMap = {};
testStudentMap = {};
studentDatastore = new StudentDatastore(userStudentMap, testStudentMap);
});
userStudentMap = {}
testStudentMap = {}
studentDatastore = new StudentDatastore(userStudentMap, testStudentMap)
})
QUnit.module('#listStudentIds');
QUnit.module('#listStudentIds')
test('returns the definitive list of known students', function() {
const studentIds = ['1101', '1102', '1103'];
studentDatastore.setStudentIds(studentIds);
const storedStudentIds = studentDatastore.listStudentIds();
strictEqual(storedStudentIds.length, 3, 'datastore contains 3 students');
deepEqual(storedStudentIds, studentIds);
});
const studentIds = ['1101', '1102', '1103']
studentDatastore.setStudentIds(studentIds)
const storedStudentIds = studentDatastore.listStudentIds()
strictEqual(storedStudentIds.length, 3, 'datastore contains 3 students')
deepEqual(storedStudentIds, studentIds)
})
QUnit.module('#setStudentIds');
QUnit.module('#setStudentIds')
test('removes stored user students not represented in the list of student ids', function() {
const students = [{ id: '1103' }, { id: '1101' }, { id: '1102' }];
studentDatastore.addUserStudents(students);
studentDatastore.setStudentIds(['1102']);
const storedStudents = studentDatastore.listStudents();
strictEqual(storedStudents.length, 1, 'datastore contains 1 student');
equal(storedStudents[0].id, '1102');
});
const students = [{id: '1103'}, {id: '1101'}, {id: '1102'}]
studentDatastore.addUserStudents(students)
studentDatastore.setStudentIds(['1102'])
const storedStudents = studentDatastore.listStudents()
strictEqual(storedStudents.length, 1, 'datastore contains 1 student')
equal(storedStudents[0].id, '1102')
})
test('removes stored test students not represented in the list of student ids', function() {
const students = [{ id: '1103' }, { id: '1101' }, { id: '1102' }];
studentDatastore.addTestStudents(students);
studentDatastore.setStudentIds(['1102']);
const storedStudents = studentDatastore.listStudents();
strictEqual(storedStudents.length, 1, 'datastore contains 1 student');
equal(storedStudents[0].id, '1102');
});
const students = [{id: '1103'}, {id: '1101'}, {id: '1102'}]
studentDatastore.addTestStudents(students)
studentDatastore.setStudentIds(['1102'])
const storedStudents = studentDatastore.listStudents()
strictEqual(storedStudents.length, 1, 'datastore contains 1 student')
equal(storedStudents[0].id, '1102')
})
QUnit.module('#listStudents');
QUnit.module('#listStudents')
test('returns the students stored in order of the saved student ids', function() {
const students = [{ id: '1103' }, { id: '1101' }, { id: '1102' }];
studentDatastore.addUserStudents(students);
studentDatastore.setStudentIds(['1101', '1102', '1103']);
const storedStudents = studentDatastore.listStudents();
strictEqual(storedStudents.length, 3, 'datastore contains 3 students');
deepEqual(storedStudents, _.sortBy(students, 'id'));
});
const students = [{id: '1103'}, {id: '1101'}, {id: '1102'}]
studentDatastore.addUserStudents(students)
studentDatastore.setStudentIds(['1101', '1102', '1103'])
const storedStudents = studentDatastore.listStudents()
strictEqual(storedStudents.length, 3, 'datastore contains 3 students')
deepEqual(storedStudents, _.sortBy(students, 'id'))
})
test('includes test students', function() {
const students = [{ id: '1103' }, { id: '1101' }, { id: '1102' }];
studentDatastore.addUserStudents(students.slice(0, 2));
studentDatastore.addTestStudents(students.slice(2, 3));
studentDatastore.setStudentIds(['1101', '1102', '1103']);
const storedStudents = studentDatastore.listStudents();
strictEqual(storedStudents.length, 3, 'datastore contains 3 students');
deepEqual(storedStudents, _.sortBy(students, 'id'));
});
const students = [{id: '1103'}, {id: '1101'}, {id: '1102'}]
studentDatastore.addUserStudents(students.slice(0, 2))
studentDatastore.addTestStudents(students.slice(2, 3))
studentDatastore.setStudentIds(['1101', '1102', '1103'])
const storedStudents = studentDatastore.listStudents()
strictEqual(storedStudents.length, 3, 'datastore contains 3 students')
deepEqual(storedStudents, _.sortBy(students, 'id'))
})
test('includes students stored directly into the original userStudentMap', function() {
studentDatastore.setStudentIds(['1101', '1102', '1103']);
const students = [{ id: '1103' }, { id: '1101' }, { id: '1102' }];
Object.assign(userStudentMap, _.keyBy(students, 'id'));
const storedStudents = studentDatastore.listStudents();
strictEqual(storedStudents.length, 3, 'datastore contains 3 students');
deepEqual(storedStudents, _.sortBy(students, 'id'));
});
studentDatastore.setStudentIds(['1101', '1102', '1103'])
const students = [{id: '1103'}, {id: '1101'}, {id: '1102'}]
Object.assign(userStudentMap, _.keyBy(students, 'id'))
const storedStudents = studentDatastore.listStudents()
strictEqual(storedStudents.length, 3, 'datastore contains 3 students')
deepEqual(storedStudents, _.sortBy(students, 'id'))
})
test('includes students stored directly into the original testStudentMap', function() {
studentDatastore.setStudentIds(['1101', '1102', '1103']);
const students = [{ id: '1103' }, { id: '1101' }, { id: '1102' }];
Object.assign(testStudentMap, _.keyBy(students, 'id'));
const storedStudents = studentDatastore.listStudents();
strictEqual(storedStudents.length, 3, 'datastore contains 3 students');
deepEqual(storedStudents, _.sortBy(students, 'id'));
});
studentDatastore.setStudentIds(['1101', '1102', '1103'])
const students = [{id: '1103'}, {id: '1101'}, {id: '1102'}]
Object.assign(testStudentMap, _.keyBy(students, 'id'))
const storedStudents = studentDatastore.listStudents()
strictEqual(storedStudents.length, 3, 'datastore contains 3 students')
deepEqual(storedStudents, _.sortBy(students, 'id'))
})
test('includes placeholder students for student ids not matching a stored student object', function() {
const students = [{ id: '1103' }, { id: '1101' }];
studentDatastore.addUserStudents(students);
studentDatastore.setStudentIds(['1101', '1102', '1103']);
const placeholderStudent = studentDatastore.listStudents().find(student => student.id === '1102');
strictEqual(placeholderStudent.isPlaceholder, true);
});
});
const students = [{id: '1103'}, {id: '1101'}]
studentDatastore.addUserStudents(students)
studentDatastore.setStudentIds(['1101', '1102', '1103'])
const placeholderStudent = studentDatastore
.listStudents()
.find(student => student.id === '1102')
strictEqual(placeholderStudent.isPlaceholder, true)
})
})

View File

@ -31,11 +31,7 @@ QUnit.module('AssignmentMuterDialogManager', suiteHooks => {
})
function createManager() {
return new AssignmentMuterDialogManager(
assignment,
url,
submissionsLoaded
)
return new AssignmentMuterDialogManager(assignment, url, submissionsLoaded)
}
QUnit.module('#assignment', () => {

View File

@ -16,82 +16,82 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import * as EnterGradesAsSetting from 'jsx/gradezilla/shared/EnterGradesAsSetting';
import * as EnterGradesAsSetting from 'jsx/gradezilla/shared/EnterGradesAsSetting'
QUnit.module('EnterGradesAsSetting', () => {
QUnit.module('.defaultOptionForGradingType', () => {
test('is "points" for the "points" grading type', () => {
equal(EnterGradesAsSetting.defaultOptionForGradingType('points'), 'points');
});
equal(EnterGradesAsSetting.defaultOptionForGradingType('points'), 'points')
})
test('is "percent" for the "percent" grading type', () => {
equal(EnterGradesAsSetting.defaultOptionForGradingType('percent'), 'percent');
});
equal(EnterGradesAsSetting.defaultOptionForGradingType('percent'), 'percent')
})
test('is "gradingScheme" for the "gpa_scale" grading type', () => {
equal(EnterGradesAsSetting.defaultOptionForGradingType('gpa_scale'), 'gradingScheme');
});
equal(EnterGradesAsSetting.defaultOptionForGradingType('gpa_scale'), 'gradingScheme')
})
test('is "gradingScheme" for the "letter_grade" grading type', () => {
equal(EnterGradesAsSetting.defaultOptionForGradingType('letter_grade'), 'gradingScheme');
});
equal(EnterGradesAsSetting.defaultOptionForGradingType('letter_grade'), 'gradingScheme')
})
test('is "passFail" for the "pass_fail" grading type', () => {
equal(EnterGradesAsSetting.defaultOptionForGradingType('pass_fail'), 'passFail');
});
equal(EnterGradesAsSetting.defaultOptionForGradingType('pass_fail'), 'passFail')
})
test('does not exist for the "not_graded" grading type', () => {
strictEqual(EnterGradesAsSetting.defaultOptionForGradingType('not_graded'), null);
});
});
strictEqual(EnterGradesAsSetting.defaultOptionForGradingType('not_graded'), null)
})
})
QUnit.module('.optionsForGradingType', () => {
test('includes "points" for the "points" grading type', () => {
ok(EnterGradesAsSetting.optionsForGradingType('points').includes('points'));
});
ok(EnterGradesAsSetting.optionsForGradingType('points').includes('points'))
})
test('includes "percent" for the "points" grading type', () => {
ok(EnterGradesAsSetting.optionsForGradingType('points').includes('percent'));
});
ok(EnterGradesAsSetting.optionsForGradingType('points').includes('percent'))
})
test('includes "points" for the "percent" grading type', () => {
ok(EnterGradesAsSetting.optionsForGradingType('percent').includes('points'));
});
ok(EnterGradesAsSetting.optionsForGradingType('percent').includes('points'))
})
test('includes "percent" for the "percent" grading type', () => {
ok(EnterGradesAsSetting.optionsForGradingType('percent').includes('percent'));
});
ok(EnterGradesAsSetting.optionsForGradingType('percent').includes('percent'))
})
test('includes "points" for the "gpa_scale" grading type', () => {
ok(EnterGradesAsSetting.optionsForGradingType('gpa_scale').includes('points'));
});
ok(EnterGradesAsSetting.optionsForGradingType('gpa_scale').includes('points'))
})
test('includes "percent" for the "gpa_scale" grading type', () => {
ok(EnterGradesAsSetting.optionsForGradingType('gpa_scale').includes('percent'));
});
ok(EnterGradesAsSetting.optionsForGradingType('gpa_scale').includes('percent'))
})
test('includes "gradingScheme" for the "gpa_scale" grading type', () => {
ok(EnterGradesAsSetting.optionsForGradingType('gpa_scale').includes('gradingScheme'));
});
ok(EnterGradesAsSetting.optionsForGradingType('gpa_scale').includes('gradingScheme'))
})
test('includes "points" for the "letter_grade" grading type', () => {
ok(EnterGradesAsSetting.optionsForGradingType('letter_grade').includes('points'));
});
ok(EnterGradesAsSetting.optionsForGradingType('letter_grade').includes('points'))
})
test('includes "percent" for the "letter_grade" grading type', () => {
ok(EnterGradesAsSetting.optionsForGradingType('letter_grade').includes('percent'));
});
ok(EnterGradesAsSetting.optionsForGradingType('letter_grade').includes('percent'))
})
test('includes "gradingScheme" for the "letter_grade" grading type', () => {
ok(EnterGradesAsSetting.optionsForGradingType('letter_grade').includes('gradingScheme'));
});
ok(EnterGradesAsSetting.optionsForGradingType('letter_grade').includes('gradingScheme'))
})
test('includes "passFail" for the "pass_fail" grading type', () => {
ok(EnterGradesAsSetting.optionsForGradingType('pass_fail').includes('passFail'));
});
ok(EnterGradesAsSetting.optionsForGradingType('pass_fail').includes('passFail'))
})
test('do not exist for the "not_graded" grading type', () => {
deepEqual(EnterGradesAsSetting.optionsForGradingType('not_graded'), []);
});
});
});
deepEqual(EnterGradesAsSetting.optionsForGradingType('not_graded'), [])
})
})
})

View File

@ -16,49 +16,49 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import TextMeasure from 'jsx/gradezilla/shared/helpers/TextMeasure';
import TextMeasure from 'jsx/gradezilla/shared/helpers/TextMeasure'
QUnit.module('TextMeasure', function(hooks) {
let $fixture;
let $fixture
hooks.beforeEach(function() {
$fixture = document.createElement('div');
document.body.appendChild($fixture);
$fixture = document.createElement('div')
document.body.appendChild($fixture)
$fixture.innerHTML = '<div id="content"></div>';
});
$fixture.innerHTML = '<div id="content"></div>'
})
hooks.afterEach(function() {
$fixture.remove();
});
$fixture.remove()
})
QUnit.module('getWidth', function() {
test('returns a numerical width for the given text', function() {
const width = TextMeasure.getWidth('example');
equal(typeof width, 'number');
});
const width = TextMeasure.getWidth('example')
equal(typeof width, 'number')
})
test('returns integers', function() {
const width = TextMeasure.getWidth('example');
strictEqual(width, Math.floor(width));
});
const width = TextMeasure.getWidth('example')
strictEqual(width, Math.floor(width))
})
test('returns larger numbers for wider text', function() {
const orderedWords = ['a', 'aa', 'aaa'];
const orderedWidths = ['aaa', 'a', 'aa'].map(TextMeasure.getWidth).sort();
deepEqual(orderedWidths, orderedWords.map(TextMeasure.getWidth));
});
const orderedWords = ['a', 'aa', 'aaa']
const orderedWidths = ['aaa', 'a', 'aa'].map(TextMeasure.getWidth).sort()
deepEqual(orderedWidths, orderedWords.map(TextMeasure.getWidth))
})
test('creates a "text-measure" element attached to the "content" element', function() {
TextMeasure.getWidth('example');
const $textMeasure = document.getElementById('text-measure');
equal($textMeasure.parentElement, document.getElementById('content'));
});
TextMeasure.getWidth('example')
const $textMeasure = document.getElementById('text-measure')
equal($textMeasure.parentElement, document.getElementById('content'))
})
test('creates only one "text-measure" element', function() {
TextMeasure.getWidth('example');
TextMeasure.getWidth('sample');
strictEqual(document.getElementById('content').children.length, 1);
});
});
});
TextMeasure.getWidth('example')
TextMeasure.getWidth('sample')
strictEqual(document.getElementById('content').children.length, 1)
})
})
})