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:
parent
08e9fbcca2
commit
f54e1ec1b9
|
@ -30,7 +30,7 @@ const getGradebookTab = () => UserSettings.contextGet('gradebook_tab')
|
||||||
const setGradebookTab = view => UserSettings.contextSet('gradebook_tab', view)
|
const setGradebookTab = view => UserSettings.contextSet('gradebook_tab', view)
|
||||||
|
|
||||||
class GradebookRouter extends Backbone.Router {
|
class GradebookRouter extends Backbone.Router {
|
||||||
static initClass () {
|
static initClass() {
|
||||||
this.prototype.routes = {
|
this.prototype.routes = {
|
||||||
'': 'tab',
|
'': 'tab',
|
||||||
'tab-assignment': 'tabAssignment',
|
'tab-assignment': 'tabAssignment',
|
||||||
|
@ -39,13 +39,13 @@ class GradebookRouter extends Backbone.Router {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
initialize () {
|
initialize() {
|
||||||
this.isLoaded = false
|
this.isLoaded = false
|
||||||
this.views = {}
|
this.views = {}
|
||||||
ENV.GRADEBOOK_OPTIONS.assignmentOrOutcome = getGradebookTab();
|
ENV.GRADEBOOK_OPTIONS.assignmentOrOutcome = getGradebookTab()
|
||||||
ENV.GRADEBOOK_OPTIONS.navigate = this.navigate.bind(this);
|
ENV.GRADEBOOK_OPTIONS.navigate = this.navigate.bind(this)
|
||||||
this.views.assignment = new Gradebook(this.gradebookOptions());
|
this.views.assignment = new Gradebook(this.gradebookOptions())
|
||||||
this.views.assignment.initialize();
|
this.views.assignment.initialize()
|
||||||
if (ENV.GRADEBOOK_OPTIONS.outcome_gradebook_enabled) {
|
if (ENV.GRADEBOOK_OPTIONS.outcome_gradebook_enabled) {
|
||||||
this.views.outcome = this.initOutcomes()
|
this.views.outcome = this.initOutcomes()
|
||||||
this.renderPagination(0, 0)
|
this.renderPagination(0, 0)
|
||||||
|
@ -54,15 +54,15 @@ class GradebookRouter extends Backbone.Router {
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
gradebookOptions () {
|
gradebookOptions() {
|
||||||
return {
|
return {
|
||||||
...ENV.GRADEBOOK_OPTIONS,
|
...ENV.GRADEBOOK_OPTIONS,
|
||||||
locale: ENV.LOCALE,
|
locale: ENV.LOCALE,
|
||||||
currentUserId: ENV.current_user_id
|
currentUserId: ENV.current_user_id
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
initOutcomes () {
|
initOutcomes() {
|
||||||
const book = new OutcomeGradebookView({
|
const book = new OutcomeGradebookView({
|
||||||
el: $('.outcome-gradebook'),
|
el: $('.outcome-gradebook'),
|
||||||
gradebook: this.views.assignment,
|
gradebook: this.views.assignment,
|
||||||
|
@ -74,12 +74,16 @@ class GradebookRouter extends Backbone.Router {
|
||||||
|
|
||||||
renderPagination(page, pageCount) {
|
renderPagination(page, pageCount) {
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<Paginator page={page} pageCount={pageCount} loadPage={(p) => this.views.outcome.loadPage(p)} />,
|
<Paginator
|
||||||
document.getElementById("outcome-gradebook-paginator")
|
page={page}
|
||||||
|
pageCount={pageCount}
|
||||||
|
loadPage={p => this.views.outcome.loadPage(p)}
|
||||||
|
/>,
|
||||||
|
document.getElementById('outcome-gradebook-paginator')
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
tabOutcome () {
|
tabOutcome() {
|
||||||
window.tab = 'outcome'
|
window.tab = 'outcome'
|
||||||
$('.assignment-gradebook-container').addClass('hidden')
|
$('.assignment-gradebook-container').addClass('hidden')
|
||||||
$('.outcome-gradebook-container > div').removeClass('hidden')
|
$('.outcome-gradebook-container > div').removeClass('hidden')
|
||||||
|
@ -87,7 +91,7 @@ class GradebookRouter extends Backbone.Router {
|
||||||
return setGradebookTab('outcome')
|
return setGradebookTab('outcome')
|
||||||
}
|
}
|
||||||
|
|
||||||
tabAssignment () {
|
tabAssignment() {
|
||||||
window.tab = 'assignment'
|
window.tab = 'assignment'
|
||||||
$('.outcome-gradebook-container > div').addClass('hidden')
|
$('.outcome-gradebook-container > div').addClass('hidden')
|
||||||
$('.assignment-gradebook-container').removeClass('hidden')
|
$('.assignment-gradebook-container').removeClass('hidden')
|
||||||
|
@ -95,10 +99,10 @@ class GradebookRouter extends Backbone.Router {
|
||||||
return setGradebookTab('assignment')
|
return setGradebookTab('assignment')
|
||||||
}
|
}
|
||||||
|
|
||||||
tab () {
|
tab() {
|
||||||
let view = getGradebookTab()
|
let view = getGradebookTab()
|
||||||
window.tab = view
|
window.tab = view
|
||||||
if ((view !== 'outcome') || !this.views.outcome) {
|
if (view !== 'outcome' || !this.views.outcome) {
|
||||||
view = 'assignment'
|
view = 'assignment'
|
||||||
}
|
}
|
||||||
$('.assignment-gradebook-container, .outcome-gradebook-container > div').addClass('hidden')
|
$('.assignment-gradebook-container, .outcome-gradebook-container > div').addClass('hidden')
|
||||||
|
@ -107,7 +111,7 @@ class GradebookRouter extends Backbone.Router {
|
||||||
this.views[view].onShow()
|
this.views[view].onShow()
|
||||||
return setGradebookTab(view)
|
return setGradebookTab(view)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GradebookRouter.initClass()
|
GradebookRouter.initClass()
|
||||||
|
|
||||||
new GradebookRouter()
|
new GradebookRouter()
|
||||||
|
|
|
@ -20,71 +20,78 @@ import $ from 'jquery'
|
||||||
import cheaterDepaginate from '../shared/CheatDepaginator'
|
import cheaterDepaginate from '../shared/CheatDepaginator'
|
||||||
import StudentContentDataLoader from './default_gradebook/DataLoader/StudentContentDataLoader'
|
import StudentContentDataLoader from './default_gradebook/DataLoader/StudentContentDataLoader'
|
||||||
|
|
||||||
function getStudentIds (courseId) {
|
function getStudentIds(courseId) {
|
||||||
const url = `/courses/${courseId}/gradebook/user_ids`;
|
const url = `/courses/${courseId}/gradebook/user_ids`
|
||||||
return $.ajaxJSON(url, 'GET', {});
|
return $.ajaxJSON(url, 'GET', {})
|
||||||
}
|
}
|
||||||
|
|
||||||
function getGradingPeriodAssignments (courseId) {
|
function getGradingPeriodAssignments(courseId) {
|
||||||
const url = `/courses/${courseId}/gradebook/grading_period_assignments`;
|
const url = `/courses/${courseId}/gradebook/grading_period_assignments`
|
||||||
return $.ajaxJSON(url, 'GET', {});
|
return $.ajaxJSON(url, 'GET', {})
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAssignmentGroups (url, params) {
|
function getAssignmentGroups(url, params) {
|
||||||
return cheaterDepaginate(url, params);
|
return cheaterDepaginate(url, params)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getContextModules (url) {
|
function getContextModules(url) {
|
||||||
return cheaterDepaginate(url);
|
return cheaterDepaginate(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCustomColumns (url) {
|
function getCustomColumns(url) {
|
||||||
return cheaterDepaginate(url, { include_hidden: true });
|
return cheaterDepaginate(url, {include_hidden: true})
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDataForColumn (columnId, url, params, cb) {
|
function getDataForColumn(columnId, url, params, cb) {
|
||||||
const columnUrl = url.replace(/:id/, columnId);
|
const columnUrl = url.replace(/:id/, columnId)
|
||||||
const augmentedCallback = data => cb(columnId, data);
|
const augmentedCallback = data => cb(columnId, data)
|
||||||
return cheaterDepaginate(columnUrl, params, augmentedCallback);
|
return cheaterDepaginate(columnUrl, params, augmentedCallback)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCustomColumnData (options, customColumnsDfd, waitForDfds) {
|
function getCustomColumnData(options, customColumnsDfd, waitForDfds) {
|
||||||
const url = options.customColumnDataURL;
|
const url = options.customColumnDataURL
|
||||||
const params = options.customColumnDataParams;
|
const params = options.customColumnDataParams
|
||||||
const cb = options.customColumnDataPageCb;
|
const cb = options.customColumnDataPageCb
|
||||||
const customColumnDataLoaded = $.Deferred();
|
const customColumnDataLoaded = $.Deferred()
|
||||||
|
|
||||||
if (url) {
|
if (url) {
|
||||||
// waitForDfds ensures that custom column data is loaded *last*
|
// waitForDfds ensures that custom column data is loaded *last*
|
||||||
$.when(...waitForDfds).then(() => {
|
$.when(...waitForDfds).then(() => {
|
||||||
if (options.customColumnIds) {
|
if (options.customColumnIds) {
|
||||||
const customColumnDataDfds = options.customColumnIds.map(columnId => getDataForColumn(columnId, url, params, cb));
|
const customColumnDataDfds = options.customColumnIds.map(columnId =>
|
||||||
$.when(...customColumnDataDfds).then(() => customColumnDataLoaded.resolve());
|
getDataForColumn(columnId, url, params, cb)
|
||||||
|
)
|
||||||
|
$.when(...customColumnDataDfds).then(() => customColumnDataLoaded.resolve())
|
||||||
} else {
|
} else {
|
||||||
customColumnsDfd.then((customColumns) => {
|
customColumnsDfd.then(customColumns => {
|
||||||
const customColumnDataDfds = customColumns.map(col => getDataForColumn(col.id, url, params, cb));
|
const customColumnDataDfds = customColumns.map(col =>
|
||||||
$.when(...customColumnDataDfds).then(() => customColumnDataLoaded.resolve());
|
getDataForColumn(col.id, url, params, cb)
|
||||||
});
|
)
|
||||||
|
$.when(...customColumnDataDfds).then(() => customColumnDataLoaded.resolve())
|
||||||
|
})
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return customColumnDataLoaded;
|
return customColumnDataLoaded
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadGradebookData (opts) {
|
function loadGradebookData(opts) {
|
||||||
const gotAssignmentGroups = getAssignmentGroups(opts.assignmentGroupsURL, opts.assignmentGroupsParams);
|
const gotAssignmentGroups = getAssignmentGroups(
|
||||||
|
opts.assignmentGroupsURL,
|
||||||
|
opts.assignmentGroupsParams
|
||||||
|
)
|
||||||
if (opts.onlyLoadAssignmentGroups) {
|
if (opts.onlyLoadAssignmentGroups) {
|
||||||
return { gotAssignmentGroups };
|
return {gotAssignmentGroups}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Begin loading Students before any other data.
|
// Begin loading Students before any other data.
|
||||||
const gotStudentIds = getStudentIds(opts.courseId);
|
const gotStudentIds = getStudentIds(opts.courseId)
|
||||||
let gotGradingPeriodAssignments;
|
let gotGradingPeriodAssignments
|
||||||
if (opts.getGradingPeriodAssignments) {
|
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({
|
const studentContentDataLoader = new StudentContentDataLoader({
|
||||||
courseId: opts.courseId,
|
courseId: opts.courseId,
|
||||||
|
@ -100,7 +107,7 @@ function loadGradebookData (opts) {
|
||||||
submissionsUrl: opts.submissionsURL
|
submissionsUrl: opts.submissionsURL
|
||||||
})
|
})
|
||||||
|
|
||||||
const gotContextModules = getContextModules(opts.contextModulesURL);
|
const gotContextModules = getContextModules(opts.contextModulesURL)
|
||||||
|
|
||||||
const gotStudents = $.Deferred()
|
const gotStudents = $.Deferred()
|
||||||
const gotSubmissions = $.Deferred()
|
const gotSubmissions = $.Deferred()
|
||||||
|
@ -112,7 +119,7 @@ function loadGradebookData (opts) {
|
||||||
})
|
})
|
||||||
|
|
||||||
// Custom Column Data will load only after custom columns and all submissions.
|
// 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 {
|
return {
|
||||||
gotAssignmentGroups,
|
gotAssignmentGroups,
|
||||||
|
@ -123,10 +130,10 @@ function loadGradebookData (opts) {
|
||||||
gotStudents,
|
gotStudents,
|
||||||
gotSubmissions,
|
gotSubmissions,
|
||||||
gotCustomColumnData
|
gotCustomColumnData
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getDataForColumn,
|
getDataForColumn,
|
||||||
loadGradebookData
|
loadGradebookData
|
||||||
};
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { bool, func, shape, string } from 'prop-types'
|
import {bool, func, shape, string} from 'prop-types'
|
||||||
import ReactDOM from 'react-dom'
|
import ReactDOM from 'react-dom'
|
||||||
import $ from 'jquery'
|
import $ from 'jquery'
|
||||||
import I18n from 'i18n!modules'
|
import I18n from 'i18n!modules'
|
||||||
|
@ -31,19 +31,19 @@ class PostGradesApp extends React.Component {
|
||||||
labelText: string.isRequired,
|
labelText: string.isRequired,
|
||||||
store: shape({
|
store: shape({
|
||||||
addChangeListener: func.isRequired,
|
addChangeListener: func.isRequired,
|
||||||
removeChangeListener: func.isRequired,
|
removeChangeListener: func.isRequired
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
renderAsButton: bool,
|
renderAsButton: bool,
|
||||||
returnFocusTo: shape({
|
returnFocusTo: shape({
|
||||||
focus: func.isRequired
|
focus: func.isRequired
|
||||||
}).isRequired
|
}).isRequired
|
||||||
};
|
}
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
renderAsButton: false
|
renderAsButton: false
|
||||||
};
|
}
|
||||||
|
|
||||||
static AppLaunch (store, returnFocusTo) {
|
static AppLaunch(store, returnFocusTo) {
|
||||||
const $dialog = $('<div class="post-grades-dialog">').dialog({
|
const $dialog = $('<div class="post-grades-dialog">').dialog({
|
||||||
title: I18n.t('Sync Grades to SIS'),
|
title: I18n.t('Sync Grades to SIS'),
|
||||||
maxWidth: 650,
|
maxWidth: 650,
|
||||||
|
@ -54,58 +54,55 @@ class PostGradesApp extends React.Component {
|
||||||
height: 450,
|
height: 450,
|
||||||
resizable: false,
|
resizable: false,
|
||||||
buttons: [],
|
buttons: [],
|
||||||
close () {
|
close() {
|
||||||
ReactDOM.unmountComponentAtNode(this);
|
ReactDOM.unmountComponentAtNode(this)
|
||||||
$(this).remove();
|
$(this).remove()
|
||||||
if (returnFocusTo) {
|
if (returnFocusTo) {
|
||||||
returnFocusTo.focus();
|
returnFocusTo.focus()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
function closeDialog (e) {
|
function closeDialog(e) {
|
||||||
e.preventDefault();
|
e.preventDefault()
|
||||||
$dialog.dialog('close');
|
$dialog.dialog('close')
|
||||||
}
|
}
|
||||||
|
|
||||||
store.reset()
|
store.reset()
|
||||||
ReactDOM.render(<PostGradesDialog store={store} closeDialog={closeDialog} />, $dialog[0]);
|
ReactDOM.render(<PostGradesDialog store={store} closeDialog={closeDialog} />, $dialog[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount() {
|
||||||
this.boundForceUpdate = this.forceUpdate.bind(this)
|
this.boundForceUpdate = this.forceUpdate.bind(this)
|
||||||
this.props.store.addChangeListener(this.boundForceUpdate)
|
this.props.store.addChangeListener(this.boundForceUpdate)
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount () { this.props.store.removeChangeListener(this.boundForceUpdate) }
|
componentWillUnmount() {
|
||||||
|
this.props.store.removeChangeListener(this.boundForceUpdate)
|
||||||
openDialog (e) {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
PostGradesApp.AppLaunch(this.props.store, this.props.returnFocusTo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
openDialog(e) {
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
PostGradesApp.AppLaunch(this.props.store, this.props.returnFocusTo)
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
const navClass = classnames({
|
const navClass = classnames({
|
||||||
'ui-button': this.props.renderAsButton
|
'ui-button': this.props.renderAsButton
|
||||||
});
|
})
|
||||||
if (this.props.renderAsButton) {
|
if (this.props.renderAsButton) {
|
||||||
return (
|
return (
|
||||||
<button
|
<button id="post-grades-button" className={navClass} onClick={this.openDialog}>
|
||||||
id="post-grades-button"
|
{this.props.labelText}
|
||||||
className={navClass}
|
</button>
|
||||||
onClick={this.openDialog}
|
)
|
||||||
>{this.props.labelText}</button>
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<a
|
<a tabIndex={0} id="post-grades-button" className={navClass} onClick={this.openDialog}>
|
||||||
tabIndex={0}
|
{this.props.labelText}
|
||||||
id="post-grades-button"
|
</a>
|
||||||
className={navClass}
|
)
|
||||||
onClick={this.openDialog}
|
|
||||||
>{this.props.labelText}</a>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,7 +135,8 @@ class PostGradesDialogCorrectionsPage extends React.Component {
|
||||||
onClick={this.ignoreErrorsThenProceed}
|
onClick={this.ignoreErrorsThenProceed}
|
||||||
>
|
>
|
||||||
{errorCount > 0 ? I18n.t('Ignore These') : I18n.t('Continue')}
|
{errorCount > 0 ? I18n.t('Ignore These') : I18n.t('Continue')}
|
||||||
<i className="icon-arrow-right" />
|
|
||||||
|
<i className="icon-arrow-right" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -63,7 +63,8 @@ class PostGradesDialogNeedsGradingPage extends React.Component {
|
||||||
className="btn btn-primary"
|
className="btn btn-primary"
|
||||||
onClick={this.props.leaveNeedsGradingPage}
|
onClick={this.props.leaveNeedsGradingPage}
|
||||||
>
|
>
|
||||||
{I18n.t('Continue')} <i className="icon-arrow-right" />
|
{I18n.t('Continue')}
|
||||||
|
<i className="icon-arrow-right" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -21,222 +21,243 @@ import _ from 'underscore'
|
||||||
import createStore from '../../shared/helpers/createStore'
|
import createStore from '../../shared/helpers/createStore'
|
||||||
import assignmentUtils from '../../gradezilla/SISGradePassback/assignmentUtils'
|
import assignmentUtils from '../../gradezilla/SISGradePassback/assignmentUtils'
|
||||||
|
|
||||||
var PostGradesStore = (state) => {
|
var PostGradesStore = state => {
|
||||||
var store = $.extend(createStore(state), {
|
var store = $.extend(createStore(state), {
|
||||||
|
reset() {
|
||||||
|
var assignments = this.getAssignments()
|
||||||
|
_.each(assignments, a => (a.please_ignore = false))
|
||||||
|
this.setState({
|
||||||
|
assignments: assignments,
|
||||||
|
pleaseShowNeedsGradingPage: false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
reset () {
|
hasAssignments() {
|
||||||
var assignments = this.getAssignments()
|
var assignments = this.getAssignments()
|
||||||
_.each(assignments, (a) => a.please_ignore = false)
|
if (assignments != undefined && assignments.length > 0) {
|
||||||
this.setState({
|
return true
|
||||||
assignments: assignments,
|
} else {
|
||||||
pleaseShowNeedsGradingPage: false
|
return false
|
||||||
})
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
hasAssignments () {
|
getSISSectionId(section_id) {
|
||||||
var assignments = this.getAssignments()
|
var sections = this.getState().sections
|
||||||
if (assignments != undefined && assignments.length > 0) {
|
return sections && sections[section_id] ? sections[section_id].sis_section_id : null
|
||||||
return true
|
},
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
getSISSectionId (section_id) {
|
allOverrideIds(a) {
|
||||||
var sections = this.getState().sections
|
var overrides = []
|
||||||
return (sections && sections[section_id]) ?
|
_.each(a.overrides, o => {
|
||||||
sections[section_id].sis_section_id :
|
overrides.push(o.course_section_id)
|
||||||
null;
|
})
|
||||||
},
|
return overrides
|
||||||
|
},
|
||||||
|
|
||||||
allOverrideIds(a) {
|
overrideForEveryone(a) {
|
||||||
var overrides = []
|
var overrides = this.allOverrideIds(a)
|
||||||
_.each(a.overrides, (o) => {
|
var sections = _.keys(this.getState().sections)
|
||||||
overrides.push(o.course_section_id)
|
var section_ids_with_no_overrides = $(sections)
|
||||||
})
|
.not(overrides)
|
||||||
return overrides
|
.get()
|
||||||
},
|
|
||||||
|
|
||||||
overrideForEveryone(a) {
|
var section_for_everyone = _.find(section_ids_with_no_overrides, o => {
|
||||||
var overrides = this.allOverrideIds(a)
|
return state.selected.id == o
|
||||||
var sections = _.keys(this.getState().sections)
|
})
|
||||||
var section_ids_with_no_overrides = $(sections).not(overrides).get();
|
return section_for_everyone
|
||||||
|
},
|
||||||
|
|
||||||
var section_for_everyone = _.find(section_ids_with_no_overrides, (o) => {
|
selectedSISId() {
|
||||||
return state.selected.id == o
|
return this.getState().selected.sis_id
|
||||||
});
|
},
|
||||||
return section_for_everyone
|
|
||||||
},
|
|
||||||
|
|
||||||
selectedSISId () {
|
setGradeBookAssignments(gradebookAssignments) {
|
||||||
return this.getState().selected.sis_id
|
var assignments = []
|
||||||
},
|
for (var id in gradebookAssignments) {
|
||||||
|
var gba = gradebookAssignments[id]
|
||||||
setGradeBookAssignments (gradebookAssignments) {
|
// Only accept assignments suitable to post, e.g. published, post_to_sis
|
||||||
var assignments = []
|
if (assignmentUtils.suitableToPost(gba)) {
|
||||||
for (var id in gradebookAssignments) {
|
// Push a copy, and only of relevant attributes
|
||||||
var gba = gradebookAssignments[id]
|
assignments.push(assignmentUtils.copyFromGradebook(gba))
|
||||||
// Only accept assignments suitable to post, e.g. published, post_to_sis
|
|
||||||
if (assignmentUtils.suitableToPost(gba)) {
|
|
||||||
// Push a copy, and only of relevant attributes
|
|
||||||
assignments.push(assignmentUtils.copyFromGradebook(gba))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// A second loop is needed to ensure non-unique name errors are included
|
|
||||||
// in hasError
|
|
||||||
_.each(assignments, (a) => {
|
|
||||||
a.original_error = assignmentUtils.hasError(assignments, a)
|
|
||||||
})
|
|
||||||
this.setState({ assignments: assignments })
|
|
||||||
},
|
|
||||||
|
|
||||||
setSections (sections) {
|
|
||||||
this.setState({ sections: sections })
|
|
||||||
this.setSelectedSection( this.getState().sectionToShow )
|
|
||||||
},
|
|
||||||
|
|
||||||
validCheck(a) {
|
|
||||||
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){
|
|
||||||
return a.overrideForThisSection.due_at != null ? true : false
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
getAssignments() {
|
|
||||||
var assignments = this.getState().assignments
|
|
||||||
var state = this.getState()
|
|
||||||
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;
|
|
||||||
});
|
|
||||||
|
|
||||||
//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) }
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
_.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';
|
|
||||||
});
|
|
||||||
|
|
||||||
//Handle assignment with overrides and the 'Everyone Else' scenario with the course currentlySelected
|
|
||||||
if(a.overrideForThisSection == undefined){ a.selectedSectionForEveryone = this.overrideForEveryone(a) }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return assignments;
|
|
||||||
},
|
|
||||||
|
|
||||||
getAssignment(assignment_id) {
|
|
||||||
var assignments = this.getAssignments()
|
|
||||||
return _.find(assignments, (a) => a.id == assignment_id)
|
|
||||||
},
|
|
||||||
|
|
||||||
setSelectedSection (section) {
|
|
||||||
var state = this.getState()
|
|
||||||
var section_id = parseInt(section)
|
|
||||||
var selected;
|
|
||||||
if (section) {
|
|
||||||
selected = {
|
|
||||||
type: "section",
|
|
||||||
id: section_id,
|
|
||||||
sis_id: this.getSISSectionId(section_id)
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
selected = {
|
|
||||||
type: "course",
|
|
||||||
id: state.course.id,
|
|
||||||
sis_id: state.course.sis_id
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({ selected: selected, sectionToShow: section })
|
|
||||||
},
|
|
||||||
|
|
||||||
updateAssignment (assignment_id, newAttrs) {
|
|
||||||
var assignments = this.getAssignments()
|
|
||||||
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)
|
|
||||||
//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) {
|
|
||||||
assignment.overrideForThisSection.due_at = date
|
|
||||||
assignment.please_ignore = false
|
|
||||||
assignment.hadOriginalErrors = true
|
|
||||||
|
|
||||||
this.setState({assignments: assignments})
|
|
||||||
}
|
|
||||||
|
|
||||||
//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){
|
|
||||||
assignment.overrideForThisSection.due_at = date
|
|
||||||
assignment.please_ignore = false
|
|
||||||
assignment.hadOriginalErrors = true
|
|
||||||
|
|
||||||
this.setState({assignments: assignments})
|
|
||||||
}
|
|
||||||
|
|
||||||
//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})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
assignmentOverrideOrigianlErrorCheck(a) {
|
|
||||||
a.hadOriginalErrors = a.hadOriginalErrors == true
|
|
||||||
},
|
|
||||||
|
|
||||||
saveAssignments () {
|
|
||||||
var assignments = assignmentUtils.withOriginalErrorsNotIgnored(this.getAssignments())
|
|
||||||
var course_id = this.getState().course.id
|
|
||||||
_.each(assignments, (a) => {
|
|
||||||
this.assignmentOverrideOrigianlErrorCheck(a)
|
|
||||||
assignmentUtils.saveAssignmentToCanvas(course_id, a)
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
postGrades() {
|
|
||||||
var assignments = assignmentUtils.notIgnored(this.getAssignments())
|
|
||||||
var selected = this.getState().selected
|
|
||||||
assignmentUtils.postGradesThroughCanvas(selected, assignments)
|
|
||||||
},
|
|
||||||
|
|
||||||
getPage () {
|
|
||||||
var state = this.getState()
|
|
||||||
if (state.pleaseShowNeedsGradingPage) {
|
|
||||||
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"
|
|
||||||
} else {
|
|
||||||
return "corrections"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
// A second loop is needed to ensure non-unique name errors are included
|
||||||
|
// in hasError
|
||||||
|
_.each(assignments, a => {
|
||||||
|
a.original_error = assignmentUtils.hasError(assignments, a)
|
||||||
|
})
|
||||||
|
this.setState({assignments: assignments})
|
||||||
|
},
|
||||||
|
|
||||||
return store
|
setSections(sections) {
|
||||||
};
|
this.setState({sections: sections})
|
||||||
|
this.setSelectedSection(this.getState().sectionToShow)
|
||||||
|
},
|
||||||
|
|
||||||
|
validCheck(a) {
|
||||||
|
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
|
||||||
|
) {
|
||||||
|
return a.overrideForThisSection.due_at != null ? true : false
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getAssignments() {
|
||||||
|
var assignments = this.getState().assignments
|
||||||
|
var state = this.getState()
|
||||||
|
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
|
||||||
|
})
|
||||||
|
|
||||||
|
//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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
_.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'
|
||||||
|
})
|
||||||
|
|
||||||
|
//Handle assignment with overrides and the 'Everyone Else' scenario with the course currentlySelected
|
||||||
|
if (a.overrideForThisSection == undefined) {
|
||||||
|
a.selectedSectionForEveryone = this.overrideForEveryone(a)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return assignments
|
||||||
|
},
|
||||||
|
|
||||||
|
getAssignment(assignment_id) {
|
||||||
|
var assignments = this.getAssignments()
|
||||||
|
return _.find(assignments, a => a.id == assignment_id)
|
||||||
|
},
|
||||||
|
|
||||||
|
setSelectedSection(section) {
|
||||||
|
var state = this.getState()
|
||||||
|
var section_id = parseInt(section)
|
||||||
|
var selected
|
||||||
|
if (section) {
|
||||||
|
selected = {
|
||||||
|
type: 'section',
|
||||||
|
id: section_id,
|
||||||
|
sis_id: this.getSISSectionId(section_id)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
selected = {
|
||||||
|
type: 'course',
|
||||||
|
id: state.course.id,
|
||||||
|
sis_id: state.course.sis_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({selected: selected, sectionToShow: section})
|
||||||
|
},
|
||||||
|
|
||||||
|
updateAssignment(assignment_id, newAttrs) {
|
||||||
|
var assignments = this.getAssignments()
|
||||||
|
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)
|
||||||
|
//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
|
||||||
|
) {
|
||||||
|
assignment.overrideForThisSection.due_at = date
|
||||||
|
assignment.please_ignore = false
|
||||||
|
assignment.hadOriginalErrors = true
|
||||||
|
|
||||||
|
this.setState({assignments: assignments})
|
||||||
|
}
|
||||||
|
|
||||||
|
//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
|
||||||
|
) {
|
||||||
|
assignment.overrideForThisSection.due_at = date
|
||||||
|
assignment.please_ignore = false
|
||||||
|
assignment.hadOriginalErrors = true
|
||||||
|
|
||||||
|
this.setState({assignments: assignments})
|
||||||
|
}
|
||||||
|
|
||||||
|
//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
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
assignmentOverrideOrigianlErrorCheck(a) {
|
||||||
|
a.hadOriginalErrors = a.hadOriginalErrors == true
|
||||||
|
},
|
||||||
|
|
||||||
|
saveAssignments() {
|
||||||
|
var assignments = assignmentUtils.withOriginalErrorsNotIgnored(this.getAssignments())
|
||||||
|
var course_id = this.getState().course.id
|
||||||
|
_.each(assignments, a => {
|
||||||
|
this.assignmentOverrideOrigianlErrorCheck(a)
|
||||||
|
assignmentUtils.saveAssignmentToCanvas(course_id, a)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
postGrades() {
|
||||||
|
var assignments = assignmentUtils.notIgnored(this.getAssignments())
|
||||||
|
var selected = this.getState().selected
|
||||||
|
assignmentUtils.postGradesThroughCanvas(selected, assignments)
|
||||||
|
},
|
||||||
|
|
||||||
|
getPage() {
|
||||||
|
var state = this.getState()
|
||||||
|
if (state.pleaseShowNeedsGradingPage) {
|
||||||
|
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'
|
||||||
|
} else {
|
||||||
|
return 'corrections'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return store
|
||||||
|
}
|
||||||
|
|
||||||
export default PostGradesStore
|
export default PostGradesStore
|
||||||
|
|
|
@ -20,230 +20,330 @@ import $ from 'jquery'
|
||||||
import _ from 'underscore'
|
import _ from 'underscore'
|
||||||
import '../../shared/helpers/createStore'
|
import '../../shared/helpers/createStore'
|
||||||
|
|
||||||
let assignmentUtils = {
|
let assignmentUtils = {
|
||||||
copyFromGradebook (assignment) {
|
copyFromGradebook(assignment) {
|
||||||
var a = _.pick(assignment, [
|
var a = _.pick(assignment, ['id', 'name', 'due_at', 'needs_grading_count', 'overrides'])
|
||||||
"id",
|
a.please_ignore = false
|
||||||
"name",
|
a.original_error = false
|
||||||
"due_at",
|
return a
|
||||||
"needs_grading_count",
|
},
|
||||||
"overrides"
|
|
||||||
])
|
|
||||||
a.please_ignore = false
|
|
||||||
a.original_error = false
|
|
||||||
return a
|
|
||||||
},
|
|
||||||
|
|
||||||
namesMatch (a, b) {
|
namesMatch(a, b) {
|
||||||
return a.name === b.name && a !== b
|
return a.name === b.name && a !== b
|
||||||
},
|
},
|
||||||
|
|
||||||
nameTooLong (a) {
|
nameTooLong(a) {
|
||||||
if (_.unescape(a.name).length > 30){
|
if (_.unescape(a.name).length > 30) {
|
||||||
return true
|
return true
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
nameEmpty (a) {
|
|
||||||
if (a.name.length == 0){
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
notUniqueName (assignments, a) {
|
|
||||||
return assignments.some(_.partial(assignmentUtils.namesMatch, a))
|
|
||||||
},
|
|
||||||
|
|
||||||
noDueDateForEveryoneElseOverride(a) {
|
|
||||||
var has_overrides = a.overrides != undefined ? a.overrides.length > 0 : false
|
|
||||||
if(has_overrides && a.overrides.length != a.sectionCount && !a.due_at){
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
withOriginalErrors (assignments) {
|
|
||||||
// This logic handles an assignment with multiple overrides
|
|
||||||
// because #setGradeBookAssignments runs on load
|
|
||||||
// it does not have a reference to what the currently viewed section is.
|
|
||||||
// Due to this an assignment with 2 overrides (one valid, one invalid)
|
|
||||||
// it will set original_errors to true. This logic checks the override
|
|
||||||
// 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}
|
|
||||||
//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}
|
|
||||||
//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}
|
|
||||||
//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}
|
|
||||||
//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}
|
|
||||||
//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}
|
|
||||||
//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)
|
|
||||||
},
|
|
||||||
|
|
||||||
withOriginalErrorsNotIgnored (assignments) {
|
|
||||||
return _.filter(assignments, function(a){ return (a.original_error || a.hadOriginalErrors) && !a.please_ignore})
|
|
||||||
},
|
|
||||||
|
|
||||||
withErrors (assignments) {
|
|
||||||
return _.filter(assignments, (a) => assignmentUtils.hasError(assignments, a))
|
|
||||||
},
|
|
||||||
|
|
||||||
notIgnored (assignments) {
|
|
||||||
return _.filter(assignments, (a) => !a.please_ignore)
|
|
||||||
},
|
|
||||||
|
|
||||||
needsGrading (assignments) {
|
|
||||||
return _.filter(assignments, (a) => a.needs_grading_count > 0)
|
|
||||||
},
|
|
||||||
|
|
||||||
hasError (assignments, a) {
|
|
||||||
////Decided to ignore
|
|
||||||
if(a.please_ignore) return false
|
|
||||||
|
|
||||||
////Not unique
|
|
||||||
if(assignmentUtils.notUniqueName(assignments, a)) return true
|
|
||||||
|
|
||||||
////Name too long
|
|
||||||
if(assignmentUtils.nameTooLong(a)) return true
|
|
||||||
|
|
||||||
////Name empty
|
|
||||||
if(assignmentUtils.nameEmpty(a)) return true
|
|
||||||
|
|
||||||
////Non-override missing due_at
|
|
||||||
var has_overrides = a.overrides != undefined ? a.overrides.length > 0 : false
|
|
||||||
if(!has_overrides && !a.due_at) return true
|
|
||||||
|
|
||||||
////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
|
|
||||||
|
|
||||||
////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
|
|
||||||
|
|
||||||
////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
|
|
||||||
|
|
||||||
////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
|
|
||||||
|
|
||||||
////'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
|
|
||||||
|
|
||||||
////Passes all tests, looks good.
|
|
||||||
return false
|
return false
|
||||||
},
|
}
|
||||||
|
},
|
||||||
|
|
||||||
suitableToPost(assignment) {
|
nameEmpty(a) {
|
||||||
return assignment.published && assignment.post_to_sis
|
if (a.name.length == 0) {
|
||||||
},
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
saveAssignmentToCanvas (course_id, assignment) {
|
notUniqueName(assignments, a) {
|
||||||
// if the date on an override is being updated confirm by checking if the due_at is an object
|
return assignments.some(_.partial(assignmentUtils.namesMatch, a))
|
||||||
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
|
|
||||||
//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() )
|
|
||||||
|
|
||||||
$.ajax(url, {
|
noDueDateForEveryoneElseOverride(a) {
|
||||||
type: 'PUT',
|
var has_overrides = a.overrides != undefined ? a.overrides.length > 0 : false
|
||||||
data: fd,
|
if (has_overrides && a.overrides.length != a.sectionCount && !a.due_at) {
|
||||||
processData: false,
|
return true
|
||||||
contentType: false,
|
} else {
|
||||||
error: (err) => {
|
return false
|
||||||
var msg = 'An error occurred saving assignment override, (' + assignment.overrideForThisSection.id + '). '
|
}
|
||||||
msg += "HTTP Error " + data.status + " : " + data.statusText
|
},
|
||||||
$.flashError(msg)
|
|
||||||
}
|
withOriginalErrors(assignments) {
|
||||||
})
|
// This logic handles an assignment with multiple overrides
|
||||||
// if there is a naming conflict on the assignment that has an override with a date
|
// because #setGradeBookAssignments runs on load
|
||||||
// that was just set AND the naming conflict is fixed we must also update the assignment
|
// it does not have a reference to what the currently viewed section is.
|
||||||
// to mock natural behavior to the user so that the naming conflict does not appear again
|
// Due to this an assignment with 2 overrides (one valid, one invalid)
|
||||||
url = '/api/v1/courses/' + course_id + '/assignments/' + assignment.id
|
// it will set original_errors to true. This logic checks the override
|
||||||
data = { assignment: {
|
// being viewed for that section. If the override is valid make
|
||||||
name: assignment.name,
|
// original error false so that the override is not shown. Vice versa
|
||||||
due_at: assignment.due_at
|
// for the invalid override on the assignment.
|
||||||
}}
|
_.each(assignments, a => {
|
||||||
$.ajax(url, {
|
if (
|
||||||
type: 'PUT',
|
a.overrideForThisSection != undefined &&
|
||||||
data: JSON.stringify(data),
|
a.recentlyUpdated != undefined &&
|
||||||
contentType: 'application/json; charset=utf-8',
|
a.recentlyUpdated == true &&
|
||||||
error: (err) => {
|
a.overrideForThisSection.due_at != null
|
||||||
var msg = 'An error occurred saving assignment (' + assignment.id + '). '
|
) {
|
||||||
msg += "HTTP Error " + data.status + " : " + data.statusText
|
a.original_error = false
|
||||||
$.flashError(msg)
|
} else if (
|
||||||
}
|
a.overrideForThisSection != undefined &&
|
||||||
})
|
a.recentlyUpdated != undefined &&
|
||||||
|
a.recentlyUpdated == false &&
|
||||||
|
a.overrideForThisSection.due_at == null
|
||||||
|
) {
|
||||||
|
a.original_error = true
|
||||||
}
|
}
|
||||||
else {
|
//for handling original error detection of a valid override for one section and an invalid override for another section
|
||||||
//allows the validation process to determine when it has been updated and can display the correct page
|
else if (
|
||||||
assignment.hadOriginalErrors = false
|
a.overrideForThisSection != undefined &&
|
||||||
var url = '/api/v1/courses/' + course_id + '/assignments/' + assignment.id
|
a.overrideForThisSection.due_at != null &&
|
||||||
var data = { assignment: {
|
!assignmentUtils.noDueDateForEveryoneElseOverride(a) &&
|
||||||
name: assignment.name,
|
a.recentlyUpdated == false &&
|
||||||
due_at: assignment.due_at
|
a.hadOriginalErrors == false
|
||||||
}}
|
) {
|
||||||
$.ajax(url, {
|
a.original_error = false
|
||||||
type: 'PUT',
|
|
||||||
data: JSON.stringify(data),
|
|
||||||
contentType: 'application/json; charset=utf-8',
|
|
||||||
error: (err) => {
|
|
||||||
var msg = 'An error occurred saving assignment (' + assignment.id + '). '
|
|
||||||
msg += "HTTP Error " + data.status + " : " + data.statusText
|
|
||||||
$.flashError(msg)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
//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
|
||||||
|
}
|
||||||
|
//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
|
||||||
|
}
|
||||||
|
//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
|
||||||
|
}
|
||||||
|
//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
|
||||||
|
}
|
||||||
|
//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)
|
||||||
|
},
|
||||||
|
|
||||||
},
|
withOriginalErrorsNotIgnored(assignments) {
|
||||||
|
return _.filter(assignments, function(a) {
|
||||||
|
return (a.original_error || a.hadOriginalErrors) && !a.please_ignore
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
withErrors(assignments) {
|
||||||
|
return _.filter(assignments, a => assignmentUtils.hasError(assignments, a))
|
||||||
|
},
|
||||||
|
|
||||||
|
notIgnored(assignments) {
|
||||||
|
return _.filter(assignments, a => !a.please_ignore)
|
||||||
|
},
|
||||||
|
|
||||||
|
needsGrading(assignments) {
|
||||||
|
return _.filter(assignments, a => a.needs_grading_count > 0)
|
||||||
|
},
|
||||||
|
|
||||||
|
hasError(assignments, a) {
|
||||||
|
////Decided to ignore
|
||||||
|
if (a.please_ignore) return false
|
||||||
|
|
||||||
|
////Not unique
|
||||||
|
if (assignmentUtils.notUniqueName(assignments, a)) return true
|
||||||
|
|
||||||
|
////Name too long
|
||||||
|
if (assignmentUtils.nameTooLong(a)) return true
|
||||||
|
|
||||||
|
////Name empty
|
||||||
|
if (assignmentUtils.nameEmpty(a)) return true
|
||||||
|
|
||||||
|
////Non-override missing due_at
|
||||||
|
var has_overrides = a.overrides != undefined ? a.overrides.length > 0 : false
|
||||||
|
if (!has_overrides && !a.due_at) return true
|
||||||
|
|
||||||
|
////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
|
||||||
|
|
||||||
|
////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
|
||||||
|
|
||||||
|
////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
|
||||||
|
|
||||||
|
////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
|
||||||
|
|
||||||
|
////'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
|
||||||
|
|
||||||
|
////Passes all tests, looks good.
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
|
||||||
|
suitableToPost(assignment) {
|
||||||
|
return assignment.published && assignment.post_to_sis
|
||||||
|
},
|
||||||
|
|
||||||
|
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'
|
||||||
|
) {
|
||||||
|
//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
|
||||||
|
//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()
|
||||||
|
)
|
||||||
|
|
||||||
// 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) }
|
|
||||||
$.ajax(url, {
|
$.ajax(url, {
|
||||||
type: 'POST',
|
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
|
||||||
|
$.flashError(msg)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// if there is a naming conflict on the assignment that has an override with a date
|
||||||
|
// 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: {
|
||||||
|
name: assignment.name,
|
||||||
|
due_at: assignment.due_at
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$.ajax(url, {
|
||||||
|
type: 'PUT',
|
||||||
data: JSON.stringify(data),
|
data: JSON.stringify(data),
|
||||||
contentType: 'application/json; charset=utf-8',
|
contentType: 'application/json; charset=utf-8',
|
||||||
success: (msg) =>{
|
error: err => {
|
||||||
if (msg.error){
|
var msg = 'An error occurred saving assignment (' + assignment.id + '). '
|
||||||
$.flashError(msg.error)
|
msg += 'HTTP Error ' + data.status + ' : ' + data.statusText
|
||||||
}else{
|
$.flashError(msg)
|
||||||
$.flashMessage(msg.message)
|
}
|
||||||
}
|
})
|
||||||
},
|
} else {
|
||||||
error: (err) => {
|
//allows the validation process to determine when it has been updated and can display the correct page
|
||||||
var msg = 'An error occurred posting grades for (' + selected.type + ' : ' + selected.id +'). '
|
assignment.hadOriginalErrors = false
|
||||||
msg += "HTTP Error " + data.status + " : " + data.statusText
|
var url = '/api/v1/courses/' + course_id + '/assignments/' + assignment.id
|
||||||
|
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 => {
|
||||||
|
var msg = 'An error occurred saving assignment (' + assignment.id + '). '
|
||||||
|
msg += 'HTTP Error ' + data.status + ' : ' + data.statusText
|
||||||
$.flashError(msg)
|
$.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)}
|
||||||
|
$.ajax(url, {
|
||||||
|
type: 'POST',
|
||||||
|
data: JSON.stringify(data),
|
||||||
|
contentType: 'application/json; charset=utf-8',
|
||||||
|
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
|
||||||
|
$.flashError(msg)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default assignmentUtils
|
export default assignmentUtils
|
||||||
|
|
|
@ -16,70 +16,92 @@
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import _ from 'underscore';
|
import _ from 'underscore'
|
||||||
import GradingPeriodsHelper from '../grading/helpers/GradingPeriodsHelper';
|
import GradingPeriodsHelper from '../grading/helpers/GradingPeriodsHelper'
|
||||||
|
|
||||||
function submissionGradingPeriodInformation (assignment, student) {
|
function submissionGradingPeriodInformation(assignment, student) {
|
||||||
const submissionInfo = assignment.effectiveDueDates[student.id] || {};
|
const submissionInfo = assignment.effectiveDueDates[student.id] || {}
|
||||||
return {
|
return {
|
||||||
gradingPeriodID: submissionInfo.grading_period_id,
|
gradingPeriodID: submissionInfo.grading_period_id,
|
||||||
inClosedGradingPeriod: submissionInfo.in_closed_grading_period
|
inClosedGradingPeriod: submissionInfo.in_closed_grading_period
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function hiddenFromStudent (assignment, student) {
|
function hiddenFromStudent(assignment, student) {
|
||||||
if (assignment.only_visible_to_overrides) {
|
if (assignment.only_visible_to_overrides) {
|
||||||
return !_.contains(assignment.assignment_visibility, student.id);
|
return !_.contains(assignment.assignment_visibility, student.id)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
function gradingPeriodInfoForCell (assignment, student, selectedGradingPeriodID) {
|
function gradingPeriodInfoForCell(assignment, student, selectedGradingPeriodID) {
|
||||||
const specificPeriodSelected = !GradingPeriodsHelper.isAllGradingPeriods(selectedGradingPeriodID);
|
const specificPeriodSelected = !GradingPeriodsHelper.isAllGradingPeriods(selectedGradingPeriodID)
|
||||||
const { gradingPeriodID, inClosedGradingPeriod } = submissionGradingPeriodInformation(assignment, student);
|
const {gradingPeriodID, inClosedGradingPeriod} = submissionGradingPeriodInformation(
|
||||||
const inNoGradingPeriod = !gradingPeriodID;
|
assignment,
|
||||||
const inOtherGradingPeriod = !!gradingPeriodID && specificPeriodSelected &&
|
student
|
||||||
selectedGradingPeriodID !== gradingPeriodID;
|
)
|
||||||
|
const inNoGradingPeriod = !gradingPeriodID
|
||||||
|
const inOtherGradingPeriod =
|
||||||
|
!!gradingPeriodID && specificPeriodSelected && selectedGradingPeriodID !== gradingPeriodID
|
||||||
|
|
||||||
return {
|
return {
|
||||||
inNoGradingPeriod,
|
inNoGradingPeriod,
|
||||||
inOtherGradingPeriod,
|
inOtherGradingPeriod,
|
||||||
inClosedGradingPeriod
|
inClosedGradingPeriod
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function cellMappingsForMultipleGradingPeriods (assignment, student, selectedGradingPeriodID, isAdmin) {
|
function cellMappingsForMultipleGradingPeriods(
|
||||||
const specificPeriodSelected = !GradingPeriodsHelper.isAllGradingPeriods(selectedGradingPeriodID);
|
assignment,
|
||||||
const { gradingPeriodID, inClosedGradingPeriod } = submissionGradingPeriodInformation(assignment, student);
|
student,
|
||||||
const gradingPeriodInfo = gradingPeriodInfoForCell(assignment, student, selectedGradingPeriodID);
|
selectedGradingPeriodID,
|
||||||
let cellMapping;
|
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)) {
|
if (specificPeriodSelected && (!gradingPeriodID || selectedGradingPeriodID !== gradingPeriodID)) {
|
||||||
cellMapping = { locked: true, hideGrade: true };
|
cellMapping = {locked: true, hideGrade: true}
|
||||||
} else if (!isAdmin && inClosedGradingPeriod) {
|
} else if (!isAdmin && inClosedGradingPeriod) {
|
||||||
cellMapping = { locked: true, hideGrade: false };
|
cellMapping = {locked: true, hideGrade: false}
|
||||||
} else {
|
} 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) {
|
if (!assignment.published || assignment.anonymize_students) {
|
||||||
return { locked: true, hideGrade: true };
|
return {locked: true, hideGrade: true}
|
||||||
} else if (assignment.moderated_grading && !assignment.grades_published) {
|
} else if (assignment.moderated_grading && !assignment.grades_published) {
|
||||||
return { locked: true, hideGrade: false };
|
return {locked: true, hideGrade: false}
|
||||||
} else if (hiddenFromStudent(assignment, student)) {
|
} else if (hiddenFromStudent(assignment, student)) {
|
||||||
return { locked: true, hideGrade: true };
|
return {locked: true, hideGrade: true}
|
||||||
} else if (hasGradingPeriods) {
|
} else if (hasGradingPeriods) {
|
||||||
return cellMappingsForMultipleGradingPeriods(assignment, student, selectedGradingPeriodID, isAdmin);
|
return cellMappingsForMultipleGradingPeriods(
|
||||||
|
assignment,
|
||||||
|
student,
|
||||||
|
selectedGradingPeriodID,
|
||||||
|
isAdmin
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
return { locked: false, hideGrade: false };
|
return {locked: false, hideGrade: false}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function missingSubmission (student, assignment) {
|
function missingSubmission(student, assignment) {
|
||||||
const submission = {
|
const submission = {
|
||||||
assignment_id: assignment.id,
|
assignment_id: assignment.id,
|
||||||
user_id: student.id,
|
user_id: student.id,
|
||||||
|
@ -87,53 +109,54 @@ function missingSubmission (student, assignment) {
|
||||||
late: false,
|
late: false,
|
||||||
missing: false,
|
missing: false,
|
||||||
seconds_late: 0
|
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 {
|
class SubmissionStateMap {
|
||||||
constructor ({ hasGradingPeriods, selectedGradingPeriodID, isAdmin }) {
|
constructor({hasGradingPeriods, selectedGradingPeriodID, isAdmin}) {
|
||||||
this.hasGradingPeriods = hasGradingPeriods;
|
this.hasGradingPeriods = hasGradingPeriods
|
||||||
this.selectedGradingPeriodID = selectedGradingPeriodID;
|
this.selectedGradingPeriodID = selectedGradingPeriodID
|
||||||
this.isAdmin = isAdmin;
|
this.isAdmin = isAdmin
|
||||||
this.submissionCellMap = {};
|
this.submissionCellMap = {}
|
||||||
this.submissionMap = {};
|
this.submissionMap = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
setup (students, assignments) {
|
setup(students, assignments) {
|
||||||
students.forEach((student) => {
|
students.forEach(student => {
|
||||||
this.submissionCellMap[student.id] = {};
|
this.submissionCellMap[student.id] = {}
|
||||||
this.submissionMap[student.id] = {};
|
this.submissionMap[student.id] = {}
|
||||||
_.each(assignments, (assignment) => {
|
_.each(assignments, assignment => {
|
||||||
this.setSubmissionCellState(student, assignment, student[`assignment_${assignment.id}`]);
|
this.setSubmissionCellState(student, assignment, student[`assignment_${assignment.id}`])
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
setSubmissionCellState (student, assignment, submission) {
|
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 = [
|
const params = [
|
||||||
assignment,
|
assignment,
|
||||||
student,
|
student,
|
||||||
this.hasGradingPeriods,
|
this.hasGradingPeriods,
|
||||||
this.selectedGradingPeriodID,
|
this.selectedGradingPeriodID,
|
||||||
this.isAdmin
|
this.isAdmin
|
||||||
];
|
]
|
||||||
|
|
||||||
this.submissionCellMap[student.id][assignment.id] = cellMapForSubmission(...params);
|
this.submissionCellMap[student.id][assignment.id] = cellMapForSubmission(...params)
|
||||||
}
|
}
|
||||||
|
|
||||||
getSubmission (userId, assignmentId) {
|
getSubmission(userId, assignmentId) {
|
||||||
return (this.submissionMap[userId] || {})[assignmentId];
|
return (this.submissionMap[userId] || {})[assignmentId]
|
||||||
}
|
}
|
||||||
|
|
||||||
getSubmissionState ({ user_id: userId, assignment_id: assignmentId }) {
|
getSubmissionState({user_id: userId, assignment_id: assignmentId}) {
|
||||||
return (this.submissionCellMap[userId] || {})[assignmentId];
|
return (this.submissionCellMap[userId] || {})[assignmentId]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SubmissionStateMap;
|
export default SubmissionStateMap
|
||||||
|
|
|
@ -21,21 +21,30 @@ import CurveGradesDialog from 'compiled/shared/CurveGradesDialog'
|
||||||
import I18n from 'i18n!gradebook'
|
import I18n from 'i18n!gradebook'
|
||||||
import 'compiled/jquery.rails_flash_notifications'
|
import 'compiled/jquery.rails_flash_notifications'
|
||||||
|
|
||||||
const CurveGradesDialogManager = {
|
const CurveGradesDialogManager = {
|
||||||
createCurveGradesAction (assignment, students, {isAdmin, contextUrl, submissionsLoaded} = {}) {
|
createCurveGradesAction(assignment, students, {isAdmin, contextUrl, submissionsLoaded} = {}) {
|
||||||
const { grading_type: gradingType, points_possible: pointsPossible } = assignment;
|
const {grading_type: gradingType, points_possible: pointsPossible} = assignment
|
||||||
return {
|
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) {
|
||||||
if (!isAdmin && assignment.inClosedGradingPeriod) {
|
// eslint-disable-line consistent-return
|
||||||
return $.flashError(I18n.t('Unable to curve grades because this assignment is due in a closed ' +
|
if (!isAdmin && assignment.inClosedGradingPeriod) {
|
||||||
'grading period for at least one student'));
|
return $.flashError(
|
||||||
}
|
I18n.t(
|
||||||
const dialog = new CurveGradesDialog({assignment, students, context_url: contextUrl});
|
'Unable to curve grades because this assignment is due in a closed ' +
|
||||||
dialog.show(onClose);
|
'grading period for at least one student'
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
};
|
const dialog = new CurveGradesDialog({assignment, students, context_url: contextUrl})
|
||||||
|
dialog.show(onClose)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
export default CurveGradesDialogManager
|
export default CurveGradesDialogManager
|
||||||
|
|
|
@ -77,7 +77,7 @@ export function createGradebook(options = {}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setFixtureHtml($fixture) {
|
export function setFixtureHtml($fixture) {
|
||||||
return $fixture.innerHTML = `
|
return ($fixture.innerHTML = `
|
||||||
<div id="application">
|
<div id="application">
|
||||||
<div id="wrapper">
|
<div id="wrapper">
|
||||||
<div data-component="GridColor"></div>
|
<div data-component="GridColor"></div>
|
||||||
|
@ -98,7 +98,7 @@ export function setFixtureHtml($fixture) {
|
||||||
<div id="gradebook_grid"></div>
|
<div id="gradebook_grid"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function stubDataLoader() {
|
export function stubDataLoader() {
|
||||||
|
|
|
@ -16,34 +16,34 @@
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import axios from 'axios';
|
import axios from 'axios'
|
||||||
import I18n from 'i18n!gradebook';
|
import I18n from 'i18n!gradebook'
|
||||||
import { underscore } from 'convert_case';
|
import {underscore} from 'convert_case'
|
||||||
|
|
||||||
function createTeacherNotesColumn (courseId) {
|
function createTeacherNotesColumn(courseId) {
|
||||||
const url = `/api/v1/courses/${courseId}/custom_gradebook_columns`;
|
const url = `/api/v1/courses/${courseId}/custom_gradebook_columns`
|
||||||
const data = {
|
const data = {
|
||||||
column: {
|
column: {
|
||||||
position: 1,
|
position: 1,
|
||||||
teacher_notes: true,
|
teacher_notes: true,
|
||||||
title: I18n.t('Notes')
|
title: I18n.t('Notes')
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
return axios.post(url, data);
|
return axios.post(url, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateTeacherNotesColumn (courseId, columnId, attr) {
|
function updateTeacherNotesColumn(courseId, columnId, attr) {
|
||||||
const url = `/api/v1/courses/${courseId}/custom_gradebook_columns/${columnId}`;
|
const url = `/api/v1/courses/${courseId}/custom_gradebook_columns/${columnId}`
|
||||||
return axios.put(url, { column: attr });
|
return axios.put(url, {column: attr})
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateSubmission (courseId, assignmentId, userId, submission) {
|
function updateSubmission(courseId, assignmentId, userId, submission) {
|
||||||
const url = `/api/v1/courses/${courseId}/assignments/${assignmentId}/submissions/${userId}`;
|
const url = `/api/v1/courses/${courseId}/assignments/${assignmentId}/submissions/${userId}`
|
||||||
return axios.put(url, { submission: underscore(submission), include: ['visibility'] });
|
return axios.put(url, {submission: underscore(submission), include: ['visibility']})
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
createTeacherNotesColumn,
|
createTeacherNotesColumn,
|
||||||
updateTeacherNotesColumn,
|
updateTeacherNotesColumn,
|
||||||
updateSubmission
|
updateSubmission
|
||||||
};
|
}
|
||||||
|
|
|
@ -16,8 +16,8 @@
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import axios from 'axios';
|
import axios from 'axios'
|
||||||
import { camelize, underscore } from 'convert_case';
|
import {camelize, underscore} from 'convert_case'
|
||||||
|
|
||||||
export const DEFAULT_LATE_POLICY_DATA = Object.freeze({
|
export const DEFAULT_LATE_POLICY_DATA = Object.freeze({
|
||||||
lateSubmissionDeductionEnabled: false,
|
lateSubmissionDeductionEnabled: false,
|
||||||
|
@ -28,40 +28,39 @@ export const DEFAULT_LATE_POLICY_DATA = Object.freeze({
|
||||||
missingSubmissionDeductionEnabled: false,
|
missingSubmissionDeductionEnabled: false,
|
||||||
missingSubmissionDeduction: 0,
|
missingSubmissionDeduction: 0,
|
||||||
newRecord: true
|
newRecord: true
|
||||||
});
|
})
|
||||||
|
|
||||||
function camelizeLatePolicyResponseData (latePolicyResponseData) {
|
function camelizeLatePolicyResponseData(latePolicyResponseData) {
|
||||||
const camelizedData = camelize(latePolicyResponseData.late_policy);
|
const camelizedData = camelize(latePolicyResponseData.late_policy)
|
||||||
return { latePolicy: camelizedData };
|
return {latePolicy: camelizedData}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fetchLatePolicy (courseId) {
|
export function fetchLatePolicy(courseId) {
|
||||||
const url = `/api/v1/courses/${courseId}/late_policy`;
|
const url = `/api/v1/courses/${courseId}/late_policy`
|
||||||
return axios.get(url)
|
return axios
|
||||||
.then(response => (
|
.get(url)
|
||||||
{ data: camelizeLatePolicyResponseData(response.data) }
|
.then(response => ({data: camelizeLatePolicyResponseData(response.data)}))
|
||||||
))
|
.catch(error => {
|
||||||
.catch((error) => {
|
|
||||||
// if we get a 404 then we know the course does not
|
// if we get a 404 then we know the course does not
|
||||||
// currently have a late policy set up
|
// currently have a late policy set up
|
||||||
if (error.response && error.response.status === 404) {
|
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 {
|
} else {
|
||||||
return Promise.reject(error);
|
return Promise.reject(error)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createLatePolicy (courseId, latePolicyData) {
|
export function createLatePolicy(courseId, latePolicyData) {
|
||||||
const url = `/api/v1/courses/${courseId}/late_policy`;
|
const url = `/api/v1/courses/${courseId}/late_policy`
|
||||||
const data = { late_policy: underscore(latePolicyData) };
|
const data = {late_policy: underscore(latePolicyData)}
|
||||||
return axios.post(url, data).then(response => (
|
return axios
|
||||||
{ data: camelizeLatePolicyResponseData(response.data) }
|
.post(url, data)
|
||||||
));
|
.then(response => ({data: camelizeLatePolicyResponseData(response.data)}))
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateLatePolicy (courseId, latePolicyData) {
|
export function updateLatePolicy(courseId, latePolicyData) {
|
||||||
const url = `/api/v1/courses/${courseId}/late_policy`;
|
const url = `/api/v1/courses/${courseId}/late_policy`
|
||||||
const data = { late_policy: underscore(latePolicyData) };
|
const data = {late_policy: underscore(latePolicyData)}
|
||||||
return axios.patch(url, data);
|
return axios.patch(url, data)
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,19 +16,19 @@
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import axios from 'axios';
|
import axios from 'axios'
|
||||||
import timezone from 'timezone';
|
import timezone from 'timezone'
|
||||||
|
|
||||||
function deserializeComment (comment) {
|
function deserializeComment(comment) {
|
||||||
const baseComment = {
|
const baseComment = {
|
||||||
id: comment.id,
|
id: comment.id,
|
||||||
createdAt: timezone.parse(comment.created_at),
|
createdAt: timezone.parse(comment.created_at),
|
||||||
comment: comment.comment,
|
comment: comment.comment,
|
||||||
editedAt: comment.edited_at && timezone.parse(comment.edited_at)
|
editedAt: comment.edited_at && timezone.parse(comment.edited_at)
|
||||||
};
|
}
|
||||||
|
|
||||||
if (!comment.author) {
|
if (!comment.author) {
|
||||||
return baseComment;
|
return baseComment
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -37,36 +37,38 @@ function deserializeComment (comment) {
|
||||||
author: comment.author.display_name,
|
author: comment.author.display_name,
|
||||||
authorAvatarUrl: comment.author.avatar_image_url,
|
authorAvatarUrl: comment.author.avatar_image_url,
|
||||||
authorUrl: comment.author.html_url
|
authorUrl: comment.author.html_url
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function deserializeComments (comments) {
|
function deserializeComments(comments) {
|
||||||
return comments.map(deserializeComment);
|
return comments.map(deserializeComment)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSubmissionComments (courseId, assignmentId, studentId) {
|
export function getSubmissionComments(courseId, assignmentId, studentId) {
|
||||||
const commentOptions = { params: { include: 'submission_comments' } };
|
const commentOptions = {params: {include: 'submission_comments'}}
|
||||||
const url = `/api/v1/courses/${courseId}/assignments/${assignmentId}/submissions/${studentId}`;
|
const url = `/api/v1/courses/${courseId}/assignments/${assignmentId}/submissions/${studentId}`
|
||||||
return axios.get(url, commentOptions)
|
return axios
|
||||||
.then(response => deserializeComments(response.data.submission_comments));
|
.get(url, commentOptions)
|
||||||
|
.then(response => deserializeComments(response.data.submission_comments))
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createSubmissionComment (courseId, assignmentId, studentId, comment) {
|
export function createSubmissionComment(courseId, assignmentId, studentId, comment) {
|
||||||
const url = `/api/v1/courses/${courseId}/assignments/${assignmentId}/submissions/${studentId}`;
|
const url = `/api/v1/courses/${courseId}/assignments/${assignmentId}/submissions/${studentId}`
|
||||||
const data = { group_comment: 0, comment: { text_comment: comment } };
|
const data = {group_comment: 0, comment: {text_comment: comment}}
|
||||||
return axios.put(url, data)
|
return axios
|
||||||
.then(response => deserializeComments(response.data.submission_comments));
|
.put(url, data)
|
||||||
|
.then(response => deserializeComments(response.data.submission_comments))
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deleteSubmissionComment (commentId) {
|
export function deleteSubmissionComment(commentId) {
|
||||||
const url = `/submission_comments/${commentId}`;
|
const url = `/submission_comments/${commentId}`
|
||||||
return axios.delete(url);
|
return axios.delete(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateSubmissionComment (commentId, comment) {
|
export function updateSubmissionComment(commentId, comment) {
|
||||||
const url = `/submission_comments/${commentId}`;
|
const url = `/submission_comments/${commentId}`
|
||||||
const data = { id: commentId, submission_comment: { comment } };
|
const data = {id: commentId, submission_comment: {comment}}
|
||||||
return axios.put(url, data).then(response => (
|
return axios
|
||||||
{ data: deserializeComment(response.data.submission_comment) }
|
.put(url, data)
|
||||||
));
|
.then(response => ({data: deserializeComment(response.data.submission_comment)}))
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,15 +16,15 @@
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import I18n from 'i18n!gradebook';
|
import I18n from 'i18n!gradebook'
|
||||||
|
|
||||||
export const filterLabels = {
|
export const filterLabels = {
|
||||||
assignmentGroups: I18n.t('Assignment Groups'),
|
assignmentGroups: I18n.t('Assignment Groups'),
|
||||||
gradingPeriods: I18n.t('Grading Periods'),
|
gradingPeriods: I18n.t('Grading Periods'),
|
||||||
modules: I18n.t('Modules'),
|
modules: I18n.t('Modules'),
|
||||||
sections: I18n.t('Sections')
|
sections: I18n.t('Sections')
|
||||||
};
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
filterLabels
|
filterLabels
|
||||||
};
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Color from 'tinycolor2';
|
import Color from 'tinycolor2'
|
||||||
|
|
||||||
export const defaultColors = {
|
export const defaultColors = {
|
||||||
salmon: '#FFE8E5',
|
salmon: '#FFE8E5',
|
||||||
|
@ -29,7 +29,7 @@ export const defaultColors = {
|
||||||
pink: '#F8EAF6',
|
pink: '#F8EAF6',
|
||||||
lavender: '#F0E8EF',
|
lavender: '#F0E8EF',
|
||||||
white: '#FFFFFF'
|
white: '#FFFFFF'
|
||||||
};
|
}
|
||||||
|
|
||||||
const defaultStatusColors = {
|
const defaultStatusColors = {
|
||||||
dropped: defaultColors.orange,
|
dropped: defaultColors.orange,
|
||||||
|
@ -37,15 +37,15 @@ const defaultStatusColors = {
|
||||||
late: defaultColors.blue,
|
late: defaultColors.blue,
|
||||||
missing: defaultColors.salmon,
|
missing: defaultColors.salmon,
|
||||||
resubmitted: defaultColors.green
|
resubmitted: defaultColors.green
|
||||||
};
|
}
|
||||||
|
|
||||||
export function statusColors (userColors = {}) {
|
export function statusColors(userColors = {}) {
|
||||||
return {
|
return {
|
||||||
...defaultStatusColors,
|
...defaultStatusColors,
|
||||||
...userColors
|
...userColors
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function darken (color, percent) {
|
export function darken(color, percent) {
|
||||||
return Color(color).darken(percent);
|
return Color(color).darken(percent)
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,15 +16,9 @@
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import I18n from 'i18n!gradebook';
|
import I18n from 'i18n!gradebook'
|
||||||
|
|
||||||
export const statuses = [
|
export const statuses = ['late', 'missing', 'resubmitted', 'dropped', 'excused']
|
||||||
'late',
|
|
||||||
'missing',
|
|
||||||
'resubmitted',
|
|
||||||
'dropped',
|
|
||||||
'excused'
|
|
||||||
];
|
|
||||||
|
|
||||||
export const statusesTitleMap = {
|
export const statusesTitleMap = {
|
||||||
late: I18n.t('Late'),
|
late: I18n.t('Late'),
|
||||||
|
@ -32,5 +26,4 @@ export const statusesTitleMap = {
|
||||||
resubmitted: I18n.t('Resubmitted'),
|
resubmitted: I18n.t('Resubmitted'),
|
||||||
dropped: I18n.t('Dropped'),
|
dropped: I18n.t('Dropped'),
|
||||||
excused: I18n.t('Excused')
|
excused: I18n.t('Excused')
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,15 +16,15 @@
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import I18n from 'i18n!gradebook';
|
import I18n from 'i18n!gradebook'
|
||||||
|
|
||||||
const primaryInfoLabels = {
|
const primaryInfoLabels = {
|
||||||
first_last: I18n.t('First, Last Name'),
|
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 primaryInfoKeys = ['first_last', 'last_first']
|
||||||
const defaultPrimaryInfo = 'first_last';
|
const defaultPrimaryInfo = 'first_last'
|
||||||
|
|
||||||
const secondaryInfoLabels = {
|
const secondaryInfoLabels = {
|
||||||
section: I18n.t('Section'),
|
section: I18n.t('Section'),
|
||||||
|
@ -32,18 +32,18 @@ const secondaryInfoLabels = {
|
||||||
integration_id: I18n.t('Integration ID'),
|
integration_id: I18n.t('Integration ID'),
|
||||||
login_id: I18n.t('Login ID'),
|
login_id: I18n.t('Login ID'),
|
||||||
none: I18n.t('None')
|
none: I18n.t('None')
|
||||||
};
|
}
|
||||||
|
|
||||||
const secondaryInfoKeys = ['section', 'sis_id', 'integration_id', 'login_id', 'none'];
|
const secondaryInfoKeys = ['section', 'sis_id', 'integration_id', 'login_id', 'none']
|
||||||
const defaultSecondaryInfo = 'none';
|
const defaultSecondaryInfo = 'none'
|
||||||
const sectionSecondaryInfo = 'section';
|
const sectionSecondaryInfo = 'section'
|
||||||
|
|
||||||
const enrollmentFilterLabels = {
|
const enrollmentFilterLabels = {
|
||||||
inactive: I18n.t('Inactive enrollments'),
|
inactive: I18n.t('Inactive enrollments'),
|
||||||
concluded: I18n.t('Concluded enrollments')
|
concluded: I18n.t('Concluded enrollments')
|
||||||
};
|
}
|
||||||
|
|
||||||
const enrollmentFilterKeys = ['inactive', 'concluded'];
|
const enrollmentFilterKeys = ['inactive', 'concluded']
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
primaryInfoKeys,
|
primaryInfoKeys,
|
||||||
|
@ -55,4 +55,4 @@ export default {
|
||||||
sectionSecondaryInfo,
|
sectionSecondaryInfo,
|
||||||
enrollmentFilterKeys,
|
enrollmentFilterKeys,
|
||||||
enrollmentFilterLabels
|
enrollmentFilterLabels
|
||||||
};
|
}
|
||||||
|
|
|
@ -16,10 +16,7 @@
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {instanceOf, string} from 'prop-types'
|
||||||
instanceOf,
|
|
||||||
string
|
|
||||||
} from 'prop-types';
|
|
||||||
|
|
||||||
const SubmissionTrayCommentPropTypes = {
|
const SubmissionTrayCommentPropTypes = {
|
||||||
id: string.isRequired,
|
id: string.isRequired,
|
||||||
|
@ -29,6 +26,6 @@ const SubmissionTrayCommentPropTypes = {
|
||||||
createdAt: instanceOf(Date).isRequired,
|
createdAt: instanceOf(Date).isRequired,
|
||||||
comment: string.isRequired,
|
comment: string.isRequired,
|
||||||
editedAt: instanceOf(Date)
|
editedAt: instanceOf(Date)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default SubmissionTrayCommentPropTypes;
|
export default SubmissionTrayCommentPropTypes
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash'
|
||||||
|
|
||||||
function createStudentPlaceholder (id) {
|
function createStudentPlaceholder(id) {
|
||||||
return {
|
return {
|
||||||
enrollments: [],
|
enrollments: [],
|
||||||
id,
|
id,
|
||||||
|
@ -27,48 +27,48 @@ function createStudentPlaceholder (id) {
|
||||||
isPlaceholder: true,
|
isPlaceholder: true,
|
||||||
loaded: false,
|
loaded: false,
|
||||||
sections: []
|
sections: []
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class StudentDatastore {
|
export default class StudentDatastore {
|
||||||
studentIds = [];
|
studentIds = []
|
||||||
|
|
||||||
constructor (userStudentMap, testStudentMap) {
|
constructor(userStudentMap, testStudentMap) {
|
||||||
this.userStudentMap = userStudentMap;
|
this.userStudentMap = userStudentMap
|
||||||
this.testStudentMap = testStudentMap;
|
this.testStudentMap = testStudentMap
|
||||||
}
|
}
|
||||||
|
|
||||||
listStudentIds () {
|
listStudentIds() {
|
||||||
return this.studentIds;
|
return this.studentIds
|
||||||
}
|
}
|
||||||
|
|
||||||
setStudentIds (studentIds) {
|
setStudentIds(studentIds) {
|
||||||
this.studentIds = studentIds;
|
this.studentIds = studentIds
|
||||||
const idsOfStoredStudents = Object.keys(this.userStudentMap);
|
const idsOfStoredStudents = Object.keys(this.userStudentMap)
|
||||||
_.difference(idsOfStoredStudents, studentIds).forEach((removedStudentId) => {
|
_.difference(idsOfStoredStudents, studentIds).forEach(removedStudentId => {
|
||||||
delete this.userStudentMap[removedStudentId];
|
delete this.userStudentMap[removedStudentId]
|
||||||
});
|
})
|
||||||
const idsOfStoredTestStudents = Object.keys(this.testStudentMap);
|
const idsOfStoredTestStudents = Object.keys(this.testStudentMap)
|
||||||
_.difference(idsOfStoredTestStudents, studentIds).forEach((removedStudentId) => {
|
_.difference(idsOfStoredTestStudents, studentIds).forEach(removedStudentId => {
|
||||||
delete this.testStudentMap[removedStudentId];
|
delete this.testStudentMap[removedStudentId]
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
addUserStudents (students) {
|
addUserStudents(students) {
|
||||||
students.forEach((student) => {
|
students.forEach(student => {
|
||||||
this.userStudentMap[student.id] = student;
|
this.userStudentMap[student.id] = student
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
addTestStudents (students) {
|
addTestStudents(students) {
|
||||||
students.forEach((student) => {
|
students.forEach(student => {
|
||||||
this.testStudentMap[student.id] = student;
|
this.testStudentMap[student.id] = student
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
listStudents () {
|
listStudents() {
|
||||||
return this.studentIds.map(id => (
|
return this.studentIds.map(
|
||||||
this.userStudentMap[id] || this.testStudentMap[id] || createStudentPlaceholder(id)
|
id => this.userStudentMap[id] || this.testStudentMap[id] || createStudentPlaceholder(id)
|
||||||
));
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,25 +20,27 @@ import INST from 'INST'
|
||||||
import $ from 'jquery'
|
import $ from 'jquery'
|
||||||
import 'jquery.instructure_misc_helpers'
|
import 'jquery.instructure_misc_helpers'
|
||||||
|
|
||||||
class DownloadSubmissionsDialogManager {
|
class DownloadSubmissionsDialogManager {
|
||||||
constructor (assignment, downloadUrlTemplate, submissionsDownloading) {
|
constructor(assignment, downloadUrlTemplate, submissionsDownloading) {
|
||||||
this.assignment = assignment;
|
this.assignment = assignment
|
||||||
this.downloadUrl = $.replaceTags(downloadUrlTemplate, 'assignment_id', assignment.id);
|
this.downloadUrl = $.replaceTags(downloadUrlTemplate, 'assignment_id', assignment.id)
|
||||||
this.showDialog = this.showDialog.bind(this);
|
this.showDialog = this.showDialog.bind(this)
|
||||||
this.validSubmissionTypes = ['online_upload', 'online_text_entry', 'online_url'];
|
this.validSubmissionTypes = ['online_upload', 'online_text_entry', 'online_url']
|
||||||
this.submissionsDownloading = submissionsDownloading;
|
this.submissionsDownloading = submissionsDownloading
|
||||||
}
|
|
||||||
|
|
||||||
isDialogEnabled () {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isDialogEnabled() {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default DownloadSubmissionsDialogManager
|
export default DownloadSubmissionsDialogManager
|
||||||
|
|
|
@ -22,7 +22,7 @@ const gradingTypeOptionMap = {
|
||||||
pass_fail: ['passFail'],
|
pass_fail: ['passFail'],
|
||||||
percent: ['points', 'percent'],
|
percent: ['points', 'percent'],
|
||||||
points: ['points', 'percent']
|
points: ['points', 'percent']
|
||||||
};
|
}
|
||||||
|
|
||||||
const gradingTypeDefaultOptionMap = {
|
const gradingTypeDefaultOptionMap = {
|
||||||
gpa_scale: 'gradingScheme',
|
gpa_scale: 'gradingScheme',
|
||||||
|
@ -30,12 +30,12 @@ const gradingTypeDefaultOptionMap = {
|
||||||
pass_fail: 'passFail',
|
pass_fail: 'passFail',
|
||||||
percent: 'percent',
|
percent: 'percent',
|
||||||
points: 'points'
|
points: 'points'
|
||||||
};
|
|
||||||
|
|
||||||
export function defaultOptionForGradingType (gradingType) {
|
|
||||||
return gradingTypeDefaultOptionMap[gradingType] || null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function optionsForGradingType (gradingType) {
|
export function defaultOptionForGradingType(gradingType) {
|
||||||
return gradingTypeOptionMap[gradingType] || [];
|
return gradingTypeDefaultOptionMap[gradingType] || null
|
||||||
|
}
|
||||||
|
|
||||||
|
export function optionsForGradingType(gradingType) {
|
||||||
|
return gradingTypeOptionMap[gradingType] || []
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,117 +19,127 @@
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import I18n from 'i18n!gradebook'
|
import I18n from 'i18n!gradebook'
|
||||||
|
|
||||||
class GradebookExportManager {
|
class GradebookExportManager {
|
||||||
static DEFAULT_POLLING_INTERVAL = 2000;
|
static DEFAULT_POLLING_INTERVAL = 2000
|
||||||
static DEFAULT_MONITORING_BASE_URL = '/api/v1/progress';
|
static DEFAULT_MONITORING_BASE_URL = '/api/v1/progress'
|
||||||
static DEFAULT_ATTACHMENT_BASE_URL = '/api/v1/users';
|
static DEFAULT_ATTACHMENT_BASE_URL = '/api/v1/users'
|
||||||
|
|
||||||
static exportCompleted (workflowState) {
|
static exportCompleted(workflowState) {
|
||||||
return workflowState === 'completed';
|
return workflowState === 'completed'
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns false if the workflowState is 'failed' or an unknown state
|
// Returns false if the workflowState is 'failed' or an unknown state
|
||||||
static exportFailed (workflowState) {
|
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) {
|
constructor(
|
||||||
this.pollingInterval = pollingInterval;
|
exportingUrl,
|
||||||
|
currentUserId,
|
||||||
|
existingExport,
|
||||||
|
pollingInterval = GradebookExportManager.DEFAULT_POLLING_INTERVAL
|
||||||
|
) {
|
||||||
|
this.pollingInterval = pollingInterval
|
||||||
|
|
||||||
this.exportingUrl = exportingUrl;
|
this.exportingUrl = exportingUrl
|
||||||
this.monitoringBaseUrl = GradebookExportManager.DEFAULT_MONITORING_BASE_URL;
|
this.monitoringBaseUrl = GradebookExportManager.DEFAULT_MONITORING_BASE_URL
|
||||||
this.attachmentBaseUrl = `${GradebookExportManager.DEFAULT_ATTACHMENT_BASE_URL}/${currentUserId}/files`;
|
this.attachmentBaseUrl = `${
|
||||||
this.currentUserId = currentUserId;
|
GradebookExportManager.DEFAULT_ATTACHMENT_BASE_URL
|
||||||
|
}/${currentUserId}/files`
|
||||||
|
this.currentUserId = currentUserId
|
||||||
|
|
||||||
if (existingExport) {
|
if (existingExport) {
|
||||||
const workflowState = existingExport.workflowState;
|
const workflowState = existingExport.workflowState
|
||||||
|
|
||||||
if (workflowState !== 'completed' && workflowState !== 'failed') {
|
if (workflowState !== 'completed' && workflowState !== 'failed') {
|
||||||
this.export = existingExport;
|
this.export = existingExport
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
monitoringUrl () {
|
|
||||||
if (!(this.export && this.export.progressId)) return undefined;
|
|
||||||
|
|
||||||
return `${this.monitoringBaseUrl}/${this.export.progressId}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
attachmentUrl () {
|
|
||||||
if (!(this.attachmentBaseUrl && this.export && this.export.attachmentId)) return undefined;
|
|
||||||
|
|
||||||
return `${this.attachmentBaseUrl}/${this.export.attachmentId}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
clearMonitor () {
|
|
||||||
if (this.exportStatusPoll) {
|
|
||||||
window.clearInterval(this.exportStatusPoll);
|
|
||||||
this.exportStatusPoll = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
monitorExport (resolve, reject) {
|
|
||||||
if (!this.monitoringUrl()) {
|
|
||||||
this.export = undefined;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (GradebookExportManager.exportCompleted(workflowState)) {
|
|
||||||
this.clearMonitor();
|
|
||||||
|
|
||||||
// Export is complete => let's get the attachment url
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
startExport (gradingPeriodId) {
|
|
||||||
if (!this.exportingUrl) {
|
|
||||||
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.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
const params = {
|
|
||||||
grading_period_id: gradingPeriodId
|
|
||||||
};
|
|
||||||
|
|
||||||
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));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
monitoringUrl() {
|
||||||
|
if (!(this.export && this.export.progressId)) return undefined
|
||||||
|
|
||||||
|
return `${this.monitoringBaseUrl}/${this.export.progressId}`
|
||||||
|
}
|
||||||
|
|
||||||
|
attachmentUrl() {
|
||||||
|
if (!(this.attachmentBaseUrl && this.export && this.export.attachmentId)) return undefined
|
||||||
|
|
||||||
|
return `${this.attachmentBaseUrl}/${this.export.attachmentId}`
|
||||||
|
}
|
||||||
|
|
||||||
|
clearMonitor() {
|
||||||
|
if (this.exportStatusPoll) {
|
||||||
|
window.clearInterval(this.exportStatusPoll)
|
||||||
|
this.exportStatusPoll = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
monitorExport(resolve, reject) {
|
||||||
|
if (!this.monitoringUrl()) {
|
||||||
|
this.export = undefined
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
if (GradebookExportManager.exportCompleted(workflowState)) {
|
||||||
|
this.clearMonitor()
|
||||||
|
|
||||||
|
// Export is complete => let's get the attachment url
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
startExport(gradingPeriodId) {
|
||||||
|
if (!this.exportingUrl) {
|
||||||
|
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.'))
|
||||||
|
}
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
grading_period_id: gradingPeriodId
|
||||||
|
}
|
||||||
|
|
||||||
|
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))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default GradebookExportManager
|
export default GradebookExportManager
|
||||||
|
|
|
@ -22,57 +22,57 @@ import I18n from 'i18n!gradezilla'
|
||||||
import $ from 'jquery'
|
import $ from 'jquery'
|
||||||
import 'jquery.instructure_misc_helpers'
|
import 'jquery.instructure_misc_helpers'
|
||||||
|
|
||||||
class ReuploadSubmissionsDialogManager {
|
class ReuploadSubmissionsDialogManager {
|
||||||
constructor (assignment, reuploadUrlTemplate) {
|
constructor(assignment, reuploadUrlTemplate) {
|
||||||
this.assignment = assignment;
|
this.assignment = assignment
|
||||||
this.reuploadUrl = $.replaceTags(reuploadUrlTemplate, 'assignment_id', assignment.id);
|
this.reuploadUrl = $.replaceTags(reuploadUrlTemplate, 'assignment_id', assignment.id)
|
||||||
this.showDialog = this.showDialog.bind(this);
|
this.showDialog = this.showDialog.bind(this)
|
||||||
}
|
|
||||||
|
|
||||||
isDialogEnabled () {
|
|
||||||
return this.assignment.hasDownloadedSubmissions;
|
|
||||||
}
|
|
||||||
|
|
||||||
getReuploadForm (cb) {
|
|
||||||
if (ReuploadSubmissionsDialogManager.reuploadForm) {
|
|
||||||
return ReuploadSubmissionsDialogManager.reuploadForm;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReuploadSubmissionsDialogManager.reuploadForm = $(
|
|
||||||
re_upload_submissions_form({ authenticityToken: authenticity_token() })
|
|
||||||
).dialog(
|
|
||||||
{
|
|
||||||
width: 400,
|
|
||||||
modal: true,
|
|
||||||
resizable: false,
|
|
||||||
autoOpen: false,
|
|
||||||
close: () => {
|
|
||||||
if (typeof cb === 'function') {
|
|
||||||
cb();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
).submit(function () {
|
|
||||||
const data = $(this).getFormData();
|
|
||||||
let submitForm = true;
|
|
||||||
|
|
||||||
if (!data.submissions_zip) {
|
|
||||||
submitForm = false;
|
|
||||||
} else if (!data.submissions_zip.match(/\.zip$/)) {
|
|
||||||
$(this).formErrors({ submissions_zip: I18n.t('Please upload files as a .zip') });
|
|
||||||
submitForm = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return submitForm;
|
|
||||||
});
|
|
||||||
|
|
||||||
return ReuploadSubmissionsDialogManager.reuploadForm;
|
|
||||||
}
|
|
||||||
|
|
||||||
showDialog (cb) {
|
|
||||||
const form = this.getReuploadForm(cb);
|
|
||||||
form.attr('action', this.reuploadUrl).dialog('open');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isDialogEnabled() {
|
||||||
|
return this.assignment.hasDownloadedSubmissions
|
||||||
|
}
|
||||||
|
|
||||||
|
getReuploadForm(cb) {
|
||||||
|
if (ReuploadSubmissionsDialogManager.reuploadForm) {
|
||||||
|
return ReuploadSubmissionsDialogManager.reuploadForm
|
||||||
|
}
|
||||||
|
|
||||||
|
ReuploadSubmissionsDialogManager.reuploadForm = $(
|
||||||
|
re_upload_submissions_form({authenticityToken: authenticity_token()})
|
||||||
|
)
|
||||||
|
.dialog({
|
||||||
|
width: 400,
|
||||||
|
modal: true,
|
||||||
|
resizable: false,
|
||||||
|
autoOpen: false,
|
||||||
|
close: () => {
|
||||||
|
if (typeof cb === 'function') {
|
||||||
|
cb()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.submit(function() {
|
||||||
|
const data = $(this).getFormData()
|
||||||
|
let submitForm = true
|
||||||
|
|
||||||
|
if (!data.submissions_zip) {
|
||||||
|
submitForm = false
|
||||||
|
} else if (!data.submissions_zip.match(/\.zip$/)) {
|
||||||
|
$(this).formErrors({submissions_zip: I18n.t('Please upload files as a .zip')})
|
||||||
|
submitForm = false
|
||||||
|
}
|
||||||
|
|
||||||
|
return submitForm
|
||||||
|
})
|
||||||
|
|
||||||
|
return ReuploadSubmissionsDialogManager.reuploadForm
|
||||||
|
}
|
||||||
|
|
||||||
|
showDialog(cb) {
|
||||||
|
const form = this.getReuploadForm(cb)
|
||||||
|
form.attr('action', this.reuploadUrl).dialog('open')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default ReuploadSubmissionsDialogManager
|
export default ReuploadSubmissionsDialogManager
|
||||||
|
|
|
@ -21,41 +21,52 @@ import I18n from 'i18n!gradebook'
|
||||||
import SetDefaultGradeDialog from 'compiled/gradezilla/SetDefaultGradeDialog'
|
import SetDefaultGradeDialog from 'compiled/gradezilla/SetDefaultGradeDialog'
|
||||||
import 'compiled/jquery.rails_flash_notifications'
|
import 'compiled/jquery.rails_flash_notifications'
|
||||||
|
|
||||||
class SetDefaultGradeDialogManager {
|
class SetDefaultGradeDialogManager {
|
||||||
constructor (assignment, students, contextId, selectedSection, isAdmin = false, submissionsLoaded = false) {
|
constructor(
|
||||||
this.assignment = assignment;
|
assignment,
|
||||||
this.students = students;
|
students,
|
||||||
this.contextId = contextId;
|
contextId,
|
||||||
this.selectedSection = selectedSection;
|
selectedSection,
|
||||||
this.isAdmin = isAdmin;
|
isAdmin = false,
|
||||||
this.submissionsLoaded = submissionsLoaded;
|
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 () {
|
getSetDefaultGradeDialogOptions() {
|
||||||
return {
|
return {
|
||||||
assignment: this.assignment,
|
assignment: this.assignment,
|
||||||
students: this.students,
|
students: this.students,
|
||||||
context_id: this.contextId,
|
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());
|
|
||||||
|
|
||||||
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'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isDialogEnabled () {
|
|
||||||
return this.submissionsLoaded;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
showDialog(cb) {
|
||||||
|
if (this.isAdmin || !this.assignment.inClosedGradingPeriod) {
|
||||||
|
const dialog = new SetDefaultGradeDialog(this.getSetDefaultGradeDialogOptions())
|
||||||
|
|
||||||
|
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'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isDialogEnabled() {
|
||||||
|
return this.submissionsLoaded
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default SetDefaultGradeDialogManager
|
export default SetDefaultGradeDialogManager
|
||||||
|
|
|
@ -16,14 +16,16 @@
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import $ from 'jquery';
|
import $ from 'jquery'
|
||||||
|
|
||||||
export function getWidth (text) {
|
export function getWidth(text) {
|
||||||
let $textMeasure = $('#text-measure');
|
let $textMeasure = $('#text-measure')
|
||||||
if (!$textMeasure.length) {
|
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 {
|
export default {
|
||||||
|
|
|
@ -17,71 +17,83 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import _ from 'underscore'
|
import _ from 'underscore'
|
||||||
function uniqueEffectiveDueDates(assignment) {
|
function uniqueEffectiveDueDates(assignment) {
|
||||||
const dueDates = _.map(assignment.effectiveDueDates, function(dueDateInfo) {
|
const dueDates = _.map(assignment.effectiveDueDates, function(dueDateInfo) {
|
||||||
const dueAt = dueDateInfo.due_at;
|
const dueAt = dueDateInfo.due_at
|
||||||
return dueAt ? new Date(dueAt) : dueAt;
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDueDateFromAssignment(assignment) {
|
const dueDates = uniqueEffectiveDueDates(assignment)
|
||||||
if (assignment.due_at) {
|
return dueDates.length === 1 ? dueDates[0] : null
|
||||||
return new Date(assignment.due_at);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const dueDates = uniqueEffectiveDueDates(assignment);
|
const assignmentHelper = {
|
||||||
return dueDates.length === 1 ? dueDates[0] : null;
|
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
|
||||||
|
}
|
||||||
|
if (aDateIsNull && bDateIsNull) {
|
||||||
|
const aHasMultipleDates = this.hasMultipleDueDates(a)
|
||||||
|
const bHasMultipleDates = this.hasMultipleDueDates(b)
|
||||||
|
if (aHasMultipleDates && !bHasMultipleDates) {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
return aDate - bDate
|
||||||
|
},
|
||||||
|
|
||||||
|
hasMultipleDueDates(assignment) {
|
||||||
|
return uniqueEffectiveDueDates(assignment).length > 1
|
||||||
|
},
|
||||||
|
|
||||||
|
getComparator(arrangeBy) {
|
||||||
|
if (arrangeBy === 'due_date') {
|
||||||
|
return this.compareByDueDate.bind(this)
|
||||||
|
}
|
||||||
|
if (arrangeBy === 'assignment_group') {
|
||||||
|
return this.compareByAssignmentGroup.bind(this)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
compareByAssignmentGroup(a, b) {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
return diffOfAssignmentGroupPosition
|
||||||
}
|
}
|
||||||
|
}
|
||||||
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 }
|
|
||||||
if (aDateIsNull && bDateIsNull) {
|
|
||||||
const aHasMultipleDates = this.hasMultipleDueDates(a);
|
|
||||||
const bHasMultipleDates = this.hasMultipleDueDates(b);
|
|
||||||
if (aHasMultipleDates && !bHasMultipleDates) { return -1 }
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
return aDate - bDate;
|
|
||||||
},
|
|
||||||
|
|
||||||
hasMultipleDueDates (assignment) {
|
|
||||||
return uniqueEffectiveDueDates(assignment).length > 1;
|
|
||||||
},
|
|
||||||
|
|
||||||
getComparator (arrangeBy) {
|
|
||||||
if (arrangeBy === 'due_date') {
|
|
||||||
return this.compareByDueDate.bind(this);
|
|
||||||
}
|
|
||||||
if (arrangeBy === 'assignment_group') {
|
|
||||||
return this.compareByAssignmentGroup.bind(this);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
compareByAssignmentGroup (a, b) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
return diffOfAssignmentGroupPosition;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default assignmentHelper
|
export default assignmentHelper
|
||||||
|
|
|
@ -19,116 +19,119 @@
|
||||||
import _ from 'underscore'
|
import _ from 'underscore'
|
||||||
import I18n from 'i18n!gradebook'
|
import I18n from 'i18n!gradebook'
|
||||||
|
|
||||||
function hasSubmitted (submission) {
|
function hasSubmitted(submission) {
|
||||||
if (submission.excused) {
|
if (submission.excused) {
|
||||||
return true;
|
return true
|
||||||
} else if (submission.latePolicyStatus) {
|
} else if (submission.latePolicyStatus) {
|
||||||
return submission.latePolicyStatus !== 'missing';
|
return submission.latePolicyStatus !== 'missing'
|
||||||
|
}
|
||||||
|
|
||||||
|
return !!(submission.submittedAt || submission.submitted_at)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSubmissionTypes(assignment) {
|
||||||
|
return assignment.submissionTypes || assignment.submission_types
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCourseId(assignment) {
|
||||||
|
return assignment.courseId || assignment.course_id
|
||||||
|
}
|
||||||
|
|
||||||
|
const MessageStudentsWhoHelper = {
|
||||||
|
settings(assignment, students) {
|
||||||
|
return {
|
||||||
|
options: this.options(assignment),
|
||||||
|
title: assignment.name,
|
||||||
|
points_possible: assignment.points_possible,
|
||||||
|
students,
|
||||||
|
context_code: `course_${getCourseId(assignment)}`,
|
||||||
|
callback: this.callbackFn.bind(this),
|
||||||
|
subjectCallback: this.generateSubjectCallbackFn(assignment)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
return !!(submission.submittedAt || submission.submitted_at);
|
options(assignment) {
|
||||||
}
|
const options = this.allOptions()
|
||||||
|
const noSubmissions = !this.hasSubmission(assignment)
|
||||||
|
if (noSubmissions) options.splice(0, 1)
|
||||||
|
return options
|
||||||
|
},
|
||||||
|
|
||||||
function getSubmissionTypes (assignment) {
|
allOptions() {
|
||||||
return (assignment.submissionTypes || assignment.submission_types);
|
return [
|
||||||
}
|
{
|
||||||
|
text: I18n.t("Haven't submitted yet"),
|
||||||
function getCourseId (assignment) {
|
subjectFn: assignment =>
|
||||||
return (assignment.courseId || assignment.course_id);
|
I18n.t('No submission for %{assignment}', {assignment: assignment.name}),
|
||||||
}
|
criteriaFn: student => !hasSubmitted(student)
|
||||||
|
},
|
||||||
const MessageStudentsWhoHelper = {
|
{
|
||||||
settings (assignment, students) {
|
text: I18n.t("Haven't been graded"),
|
||||||
return {
|
subjectFn: assignment =>
|
||||||
options: this.options(assignment),
|
I18n.t('No grade for %{assignment}', {assignment: assignment.name}),
|
||||||
title: assignment.name,
|
criteriaFn: student => !this.exists(student.score)
|
||||||
points_possible: assignment.points_possible,
|
},
|
||||||
students,
|
{
|
||||||
context_code: `course_${getCourseId(assignment)}`,
|
text: I18n.t('Scored less than'),
|
||||||
callback: this.callbackFn.bind(this),
|
cutoff: true,
|
||||||
subjectCallback: this.generateSubjectCallbackFn(assignment)
|
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
|
||||||
}
|
}
|
||||||
},
|
]
|
||||||
|
},
|
||||||
|
|
||||||
options (assignment) {
|
hasSubmission(assignment) {
|
||||||
const options = this.allOptions();
|
const submissionTypes = getSubmissionTypes(assignment)
|
||||||
const noSubmissions = !this.hasSubmission(assignment);
|
if (submissionTypes.length === 0) return false
|
||||||
if (noSubmissions) options.splice(0, 1);
|
|
||||||
return options;
|
|
||||||
},
|
|
||||||
|
|
||||||
allOptions () {
|
return _.any(
|
||||||
return [
|
submissionTypes,
|
||||||
{
|
submissionType => submissionType !== 'none' && submissionType !== 'on_paper'
|
||||||
text: I18n.t("Haven't submitted yet"),
|
)
|
||||||
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 }
|
|
||||||
),
|
|
||||||
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
|
|
||||||
},
|
|
||||||
{
|
|
||||||
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
|
|
||||||
}
|
|
||||||
];
|
|
||||||
},
|
|
||||||
|
|
||||||
hasSubmission (assignment) {
|
exists(value) {
|
||||||
const submissionTypes = getSubmissionTypes(assignment);
|
return !_.isUndefined(value) && !_.isNull(value)
|
||||||
if (submissionTypes.length === 0) return false;
|
},
|
||||||
|
|
||||||
return _.any(submissionTypes, submissionType => submissionType !== 'none' && submissionType !== 'on_paper');
|
scoreWithCutoff(student, cutoff) {
|
||||||
},
|
return this.exists(student.score) && student.score !== '' && this.exists(cutoff)
|
||||||
|
},
|
||||||
|
|
||||||
exists (value) {
|
callbackFn(selected, cutoff, students) {
|
||||||
return !_.isUndefined(value) && !_.isNull(value);
|
const criteriaFn = this.findOptionByText(selected).criteriaFn
|
||||||
},
|
const studentsMatchingCriteria = _.filter(students, student =>
|
||||||
|
criteriaFn(student.user_data, cutoff)
|
||||||
|
)
|
||||||
|
return _.map(studentsMatchingCriteria, student => student.user_data.id)
|
||||||
|
},
|
||||||
|
|
||||||
scoreWithCutoff (student, cutoff) {
|
findOptionByText(text) {
|
||||||
return this.exists(student.score)
|
return _.find(this.allOptions(), option => option.text === text)
|
||||||
&& student.score !== ''
|
},
|
||||||
&& this.exists(cutoff);
|
|
||||||
},
|
|
||||||
|
|
||||||
callbackFn (selected, cutoff, students) {
|
generateSubjectCallbackFn(assignment) {
|
||||||
const criteriaFn = this.findOptionByText(selected).criteriaFn;
|
return (selected, cutoff) => {
|
||||||
const studentsMatchingCriteria = _.filter(students, student => criteriaFn(student.user_data, cutoff));
|
const cutoffString = cutoff || ''
|
||||||
return _.map(studentsMatchingCriteria, student => student.user_data.id);
|
const subjectFn = this.findOptionByText(selected).subjectFn
|
||||||
},
|
return subjectFn(assignment, cutoffString)
|
||||||
|
|
||||||
findOptionByText (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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
}
|
||||||
export default MessageStudentsWhoHelper
|
export default MessageStudentsWhoHelper
|
||||||
|
|
|
@ -21,25 +21,24 @@ import I18n from 'i18n!gradezilla_uploads'
|
||||||
import 'spin.js/jquery.spin'
|
import 'spin.js/jquery.spin'
|
||||||
|
|
||||||
export function waitForProcessing(progress) {
|
export function waitForProcessing(progress) {
|
||||||
const dfd = $.Deferred();
|
const dfd = $.Deferred()
|
||||||
const spinner = $("#spinner").spin();
|
const spinner = $('#spinner').spin()
|
||||||
|
|
||||||
const amIDoneYet = (currentProgress) => {
|
const amIDoneYet = currentProgress => {
|
||||||
if (currentProgress.workflow_state === "completed") {
|
if (currentProgress.workflow_state === 'completed') {
|
||||||
$.ajaxJSON(ENV.uploaded_gradebook_data_path, "GET").then((uploadedGradebook) => {
|
$.ajaxJSON(ENV.uploaded_gradebook_data_path, 'GET').then(uploadedGradebook => {
|
||||||
spinner.hide();
|
spinner.hide()
|
||||||
dfd.resolve(uploadedGradebook)
|
dfd.resolve(uploadedGradebook)
|
||||||
});
|
})
|
||||||
} else if (currentProgress.workflow_state === "failed") {
|
} else if (currentProgress.workflow_state === 'failed') {
|
||||||
dfd.reject(I18n.t("Invalid CSV file. Grades could not be updated."));
|
dfd.reject(I18n.t('Invalid CSV file. Grades could not be updated.'))
|
||||||
} else {
|
} else {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
$.ajaxJSON(`/api/v1/progress/${currentProgress.id}`, "GET")
|
$.ajaxJSON(`/api/v1/progress/${currentProgress.id}`, 'GET').then(amIDoneYet)
|
||||||
.then(amIDoneYet);
|
}, 2000)
|
||||||
}, 2000);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
amIDoneYet(progress);
|
amIDoneYet(progress)
|
||||||
|
|
||||||
return dfd;
|
return dfd
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ let iframe
|
||||||
let info
|
let info
|
||||||
|
|
||||||
QUnit.module('PostGradesFrameDialog screenreader only content', {
|
QUnit.module('PostGradesFrameDialog screenreader only content', {
|
||||||
setup () {
|
setup() {
|
||||||
fakeENV.setup({LTI_LAUNCH_FRAME_ALLOWANCES: ['midi', 'media']})
|
fakeENV.setup({LTI_LAUNCH_FRAME_ALLOWANCES: ['midi', 'media']})
|
||||||
dialog = new PostGradesFrameDialog({})
|
dialog = new PostGradesFrameDialog({})
|
||||||
el = dialog.$dialog
|
el = dialog.$dialog
|
||||||
|
@ -33,7 +33,7 @@ QUnit.module('PostGradesFrameDialog screenreader only content', {
|
||||||
dialog.open()
|
dialog.open()
|
||||||
},
|
},
|
||||||
|
|
||||||
teardown () {
|
teardown() {
|
||||||
dialog.close()
|
dialog.close()
|
||||||
dialog.$dialog.remove()
|
dialog.$dialog.remove()
|
||||||
fakeENV.teardown()
|
fakeENV.teardown()
|
||||||
|
@ -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", () => {
|
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'))
|
notOk(iframe.hasClass('info_alert_outline'))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -16,194 +16,204 @@
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* 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 = {
|
const student = {
|
||||||
id: '1',
|
id: '1',
|
||||||
group_ids: ['1'],
|
group_ids: ['1'],
|
||||||
sections: ['1']
|
sections: ['1']
|
||||||
};
|
}
|
||||||
|
|
||||||
function createMap (opts = {}) {
|
function createMap(opts = {}) {
|
||||||
const defaults = {
|
const defaults = {
|
||||||
hasGradingPeriods: false,
|
hasGradingPeriods: false,
|
||||||
selectedGradingPeriodID: '0',
|
selectedGradingPeriodID: '0',
|
||||||
isAdmin: false
|
isAdmin: false
|
||||||
};
|
}
|
||||||
|
|
||||||
const params = Object.assign(defaults, opts);
|
const params = Object.assign(defaults, opts)
|
||||||
return new SubmissionStateMap(params);
|
return new SubmissionStateMap(params)
|
||||||
}
|
}
|
||||||
|
|
||||||
function createAndSetupMap (assignment, opts = {}) {
|
function createAndSetupMap(assignment, opts = {}) {
|
||||||
const map = createMap(opts);
|
const map = createMap(opts)
|
||||||
const assignments = {};
|
const assignments = {}
|
||||||
assignments[assignment.id] = assignment;
|
assignments[assignment.id] = assignment
|
||||||
map.setup([student], assignments);
|
map.setup([student], assignments)
|
||||||
return map;
|
return map
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: the spec setup above should live in a spec helper -- at the
|
// 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
|
// 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
|
// 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 () {
|
test('submission in an unpublished assignment is hidden', function() {
|
||||||
const assignment = { id: '1', published: false, effectiveDueDates: {} };
|
const assignment = {id: '1', published: false, effectiveDueDates: {}}
|
||||||
const map = createAndSetupMap(assignment, { hasGradingPeriods: false });
|
const map = createAndSetupMap(assignment, {hasGradingPeriods: false})
|
||||||
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
|
||||||
strictEqual(state.hideGrade, true);
|
strictEqual(state.hideGrade, true)
|
||||||
});
|
})
|
||||||
|
|
||||||
test('submission in a published assignment is not hidden', function () {
|
test('submission in a published assignment is not hidden', function() {
|
||||||
const assignment = { id: '1', published: true, effectiveDueDates: {} };
|
const assignment = {id: '1', published: true, effectiveDueDates: {}}
|
||||||
const map = createAndSetupMap(assignment, { hasGradingPeriods: false });
|
const map = createAndSetupMap(assignment, {hasGradingPeriods: false})
|
||||||
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
|
||||||
strictEqual(state.hideGrade, false);
|
strictEqual(state.hideGrade, false)
|
||||||
});
|
})
|
||||||
|
|
||||||
test('submission has grade hidden for a student without assignment visibility', function () {
|
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 assignment = {
|
||||||
const map = createAndSetupMap(assignment, { hasGradingPeriods: false });
|
id: '1',
|
||||||
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
published: true,
|
||||||
equal(state.hideGrade, 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 () {
|
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] = {
|
assignment.effectiveDueDates[student.id] = {
|
||||||
due_at: null,
|
due_at: null,
|
||||||
grading_period_id: null,
|
grading_period_id: null,
|
||||||
in_closed_grading_period: false
|
in_closed_grading_period: false
|
||||||
};
|
}
|
||||||
|
|
||||||
const map = createAndSetupMap(assignment, { hasGradingPeriods: false });
|
const map = createAndSetupMap(assignment, {hasGradingPeriods: false})
|
||||||
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
|
||||||
equal(state.hideGrade, false);
|
equal(state.hideGrade, false)
|
||||||
});
|
})
|
||||||
|
|
||||||
QUnit.module('SubmissionStateMap with grading periods and all grading periods selected', {
|
QUnit.module('SubmissionStateMap with grading periods and all grading periods selected', {
|
||||||
setup () {
|
setup() {
|
||||||
this.DATE_IN_CLOSED_PERIOD = '2015-07-15';
|
this.DATE_IN_CLOSED_PERIOD = '2015-07-15'
|
||||||
this.DATE_NOT_IN_CLOSED_PERIOD = '2015-08-15';
|
this.DATE_NOT_IN_CLOSED_PERIOD = '2015-08-15'
|
||||||
this.mapOptions = { hasGradingPeriods: true, selectedGradingPeriodID: '0' };
|
this.mapOptions = {hasGradingPeriods: true, selectedGradingPeriodID: '0'}
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
test('submission has grade hidden for a student without assignment visibility', function () {
|
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 assignment = {
|
||||||
const map = createAndSetupMap(assignment, this.mapOptions);
|
id: '1',
|
||||||
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
published: true,
|
||||||
equal(state.hideGrade, 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 () {
|
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] = {
|
assignment.effectiveDueDates[student.id] = {
|
||||||
due_at: this.DATE_IN_CLOSED_PERIOD,
|
due_at: this.DATE_IN_CLOSED_PERIOD,
|
||||||
grading_period_id: '1',
|
grading_period_id: '1',
|
||||||
in_closed_grading_period: true
|
in_closed_grading_period: true
|
||||||
};
|
}
|
||||||
|
|
||||||
const map = createAndSetupMap(assignment, this.mapOptions);
|
const map = createAndSetupMap(assignment, this.mapOptions)
|
||||||
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
|
||||||
equal(state.hideGrade, false);
|
equal(state.hideGrade, false)
|
||||||
});
|
})
|
||||||
|
|
||||||
test('submission has grade visible for an assigned student with assignment due outside of a closed grading period', function () {
|
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] = {
|
assignment.effectiveDueDates[student.id] = {
|
||||||
due_at: this.DATE_NOT_IN_CLOSED_PERIOD,
|
due_at: this.DATE_NOT_IN_CLOSED_PERIOD,
|
||||||
grading_period_id: '2',
|
grading_period_id: '2',
|
||||||
in_closed_grading_period: false
|
in_closed_grading_period: false
|
||||||
};
|
}
|
||||||
|
|
||||||
const map = createAndSetupMap(assignment, this.mapOptions);
|
const map = createAndSetupMap(assignment, this.mapOptions)
|
||||||
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
|
||||||
equal(state.hideGrade, false);
|
equal(state.hideGrade, false)
|
||||||
});
|
})
|
||||||
|
|
||||||
QUnit.module('SubmissionStateMap with grading periods and a non-closed grading period selected', {
|
QUnit.module('SubmissionStateMap with grading periods and a non-closed grading period selected', {
|
||||||
setup () {
|
setup() {
|
||||||
this.SELECTED_PERIOD_ID = '1';
|
this.SELECTED_PERIOD_ID = '1'
|
||||||
this.DATE_IN_SELECTED_PERIOD = '2015-08-15';
|
this.DATE_IN_SELECTED_PERIOD = '2015-08-15'
|
||||||
this.DATE_NOT_IN_SELECTED_PERIOD = '2015-10-15';
|
this.DATE_NOT_IN_SELECTED_PERIOD = '2015-10-15'
|
||||||
this.mapOptions = { hasGradingPeriods: true, selectedGradingPeriodID: this.SELECTED_PERIOD_ID };
|
this.mapOptions = {hasGradingPeriods: true, selectedGradingPeriodID: this.SELECTED_PERIOD_ID}
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
test('submission has grade hidden for a student without assignment visibility', function () {
|
test('submission has grade hidden for a student without assignment visibility', function() {
|
||||||
const assignment = { id: '1', published: true, effectiveDueDates: {} };
|
const assignment = {id: '1', published: true, effectiveDueDates: {}}
|
||||||
const map = createAndSetupMap(assignment, this.mapOptions);
|
const map = createAndSetupMap(assignment, this.mapOptions)
|
||||||
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
|
||||||
equal(state.hideGrade, true);
|
equal(state.hideGrade, true)
|
||||||
});
|
})
|
||||||
|
|
||||||
test('submission has grade hidden for an assigned student with assignment due outside of the selected grading period', function () {
|
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] = {
|
assignment.effectiveDueDates[student.id] = {
|
||||||
due_at: this.DATE_NOT_IN_SELECTED_PERIOD,
|
due_at: this.DATE_NOT_IN_SELECTED_PERIOD,
|
||||||
grading_period_id: '2',
|
grading_period_id: '2',
|
||||||
in_closed_grading_period: false
|
in_closed_grading_period: false
|
||||||
};
|
}
|
||||||
|
|
||||||
const map = createAndSetupMap(assignment, this.mapOptions);
|
const map = createAndSetupMap(assignment, this.mapOptions)
|
||||||
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
|
||||||
equal(state.hideGrade, true);
|
equal(state.hideGrade, true)
|
||||||
});
|
})
|
||||||
|
|
||||||
test('submission has grade visible for an assigned student with assignment due in the selected grading period', function () {
|
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] = {
|
assignment.effectiveDueDates[student.id] = {
|
||||||
due_at: this.DATE_IN_SELECTED_PERIOD,
|
due_at: this.DATE_IN_SELECTED_PERIOD,
|
||||||
grading_period_id: this.SELECTED_PERIOD_ID,
|
grading_period_id: this.SELECTED_PERIOD_ID,
|
||||||
in_closed_grading_period: false
|
in_closed_grading_period: false
|
||||||
};
|
}
|
||||||
|
|
||||||
const map = createAndSetupMap(assignment, this.mapOptions);
|
const map = createAndSetupMap(assignment, this.mapOptions)
|
||||||
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
|
||||||
equal(state.hideGrade, false);
|
equal(state.hideGrade, false)
|
||||||
});
|
})
|
||||||
|
|
||||||
QUnit.module('SubmissionStateMap with grading periods and a closed grading period selected', {
|
QUnit.module('SubmissionStateMap with grading periods and a closed grading period selected', {
|
||||||
setup () {
|
setup() {
|
||||||
this.SELECTED_PERIOD_ID = '1';
|
this.SELECTED_PERIOD_ID = '1'
|
||||||
this.DATE_IN_SELECTED_PERIOD = '2015-07-15';
|
this.DATE_IN_SELECTED_PERIOD = '2015-07-15'
|
||||||
this.DATE_NOT_IN_SELECTED_PERIOD = '2015-08-15';
|
this.DATE_NOT_IN_SELECTED_PERIOD = '2015-08-15'
|
||||||
this.mapOptions = { hasGradingPeriods: true, selectedGradingPeriodID: this.SELECTED_PERIOD_ID };
|
this.mapOptions = {hasGradingPeriods: true, selectedGradingPeriodID: this.SELECTED_PERIOD_ID}
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
test('submission has grade hidden for a student without assignment visibility', function () {
|
test('submission has grade hidden for a student without assignment visibility', function() {
|
||||||
const assignment = { id: '1', published: true, effectiveDueDates: {} };
|
const assignment = {id: '1', published: true, effectiveDueDates: {}}
|
||||||
const map = createAndSetupMap(assignment, this.mapOptions);
|
const map = createAndSetupMap(assignment, this.mapOptions)
|
||||||
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
|
||||||
equal(state.hideGrade, true);
|
equal(state.hideGrade, true)
|
||||||
});
|
})
|
||||||
|
|
||||||
test('submission has grade hidden for an assigned student with assignment due outside of the selected grading period', function () {
|
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] = {
|
assignment.effectiveDueDates[student.id] = {
|
||||||
due_at: this.DATE_NOT_IN_SELECTED_PERIOD,
|
due_at: this.DATE_NOT_IN_SELECTED_PERIOD,
|
||||||
grading_period_id: '2',
|
grading_period_id: '2',
|
||||||
in_closed_grading_period: false
|
in_closed_grading_period: false
|
||||||
};
|
}
|
||||||
|
|
||||||
const map = createAndSetupMap(assignment, this.mapOptions);
|
const map = createAndSetupMap(assignment, this.mapOptions)
|
||||||
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
|
||||||
equal(state.hideGrade, true);
|
equal(state.hideGrade, true)
|
||||||
});
|
})
|
||||||
|
|
||||||
test('submission has grade visible for an assigned student with assignment due in the selected grading period', function () {
|
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] = {
|
assignment.effectiveDueDates[student.id] = {
|
||||||
due_at: this.DATE_IN_SELECTED_PERIOD,
|
due_at: this.DATE_IN_SELECTED_PERIOD,
|
||||||
grading_period_id: this.SELECTED_PERIOD_ID,
|
grading_period_id: this.SELECTED_PERIOD_ID,
|
||||||
in_closed_grading_period: true
|
in_closed_grading_period: true
|
||||||
};
|
}
|
||||||
|
|
||||||
const map = createAndSetupMap(assignment, this.mapOptions);
|
const map = createAndSetupMap(assignment, this.mapOptions)
|
||||||
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
|
||||||
equal(state.hideGrade, false);
|
equal(state.hideGrade, false)
|
||||||
});
|
})
|
||||||
|
|
|
@ -16,231 +16,273 @@
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* 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 = {
|
const student = {
|
||||||
id: '1',
|
id: '1',
|
||||||
group_ids: ['1'],
|
group_ids: ['1'],
|
||||||
sections: ['1']
|
sections: ['1']
|
||||||
};
|
}
|
||||||
|
|
||||||
function createMap (opts = {}) {
|
function createMap(opts = {}) {
|
||||||
const params = {
|
const params = {
|
||||||
hasGradingPeriods: false,
|
hasGradingPeriods: false,
|
||||||
selectedGradingPeriodID: '0',
|
selectedGradingPeriodID: '0',
|
||||||
isAdmin: false,
|
isAdmin: false,
|
||||||
...opts
|
...opts
|
||||||
};
|
}
|
||||||
|
|
||||||
return new SubmissionStateMap(params);
|
return new SubmissionStateMap(params)
|
||||||
}
|
}
|
||||||
|
|
||||||
function createAndSetupMap (assignment, opts = {}) {
|
function createAndSetupMap(assignment, opts = {}) {
|
||||||
const submissionStateMap = createMap(opts);
|
const submissionStateMap = createMap(opts)
|
||||||
const assignments = {};
|
const assignments = {}
|
||||||
assignments[assignment.id] = assignment;
|
assignments[assignment.id] = assignment
|
||||||
submissionStateMap.setup([student], assignments);
|
submissionStateMap.setup([student], assignments)
|
||||||
return submissionStateMap;
|
return submissionStateMap
|
||||||
}
|
}
|
||||||
|
|
||||||
QUnit.module('SubmissionStateMap without grading periods', function (suiteHooks) {
|
QUnit.module('SubmissionStateMap without grading periods', function(suiteHooks) {
|
||||||
const dueDate = '2015-07-15';
|
const dueDate = '2015-07-15'
|
||||||
let assignment;
|
let assignment
|
||||||
let submissionStateMap;
|
let submissionStateMap
|
||||||
let options;
|
let options
|
||||||
|
|
||||||
suiteHooks.beforeEach(() => {
|
suiteHooks.beforeEach(() => {
|
||||||
options = { hasGradingPeriods: false };
|
options = {hasGradingPeriods: false}
|
||||||
assignment = { id: '1', published: true, effectiveDueDates: {} };
|
assignment = {id: '1', published: true, effectiveDueDates: {}}
|
||||||
});
|
})
|
||||||
|
|
||||||
QUnit.module('inNoGradingPeriod', function (_hooks) {
|
QUnit.module('inNoGradingPeriod', function(_hooks) {
|
||||||
test('returns undefined if submission has no grading period', function () {
|
test('returns undefined if submission has no grading period', function() {
|
||||||
assignment.effectiveDueDates[student.id] = {
|
assignment.effectiveDueDates[student.id] = {
|
||||||
due_at: dueDate,
|
due_at: dueDate,
|
||||||
in_closed_grading_period: false
|
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 () {
|
test('returns undefined if submission has a grading period', function() {
|
||||||
assignment.effectiveDueDates[student.id] = {
|
assignment.effectiveDueDates[student.id] = {
|
||||||
due_at: dueDate,
|
due_at: dueDate,
|
||||||
grading_period_id: 1,
|
grading_period_id: 1,
|
||||||
in_closed_grading_period: false
|
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) {
|
QUnit.module('inOtherGradingPeriod', function(hooks) {
|
||||||
hooks.beforeEach(() => {
|
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);
|
|
||||||
|
|
||||||
const state = submissionStateMap.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
const state = submissionStateMap.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
const state = submissionStateMap.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
|
||||||
|
|
||||||
strictEqual(state.inOtherGradingPeriod, undefined);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
QUnit.module('inClosedGradingPeriod', function (hooks) {
|
|
||||||
hooks.beforeEach(() => {
|
|
||||||
assignment.effectiveDueDates[student.id] = {
|
|
||||||
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);
|
|
||||||
|
|
||||||
const state = submissionStateMap.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
const state = submissionStateMap.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
|
||||||
|
|
||||||
strictEqual(state.inClosedGradingPeriod, undefined);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
QUnit.module('SubmissionStateMap with grading periods', function (suiteHooks) {
|
|
||||||
const dueDate = '2015-07-15';
|
|
||||||
let assignment;
|
|
||||||
let submissionStateMap;
|
|
||||||
let options;
|
|
||||||
|
|
||||||
suiteHooks.beforeEach(() => {
|
|
||||||
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 () {
|
|
||||||
assignment.effectiveDueDates[student.id] = {
|
assignment.effectiveDueDates[student.id] = {
|
||||||
due_at: dueDate,
|
due_at: dueDate,
|
||||||
in_closed_grading_period: false
|
in_closed_grading_period: false
|
||||||
}
|
}
|
||||||
submissionStateMap = createAndSetupMap(assignment, options);
|
})
|
||||||
|
|
||||||
const state = submissionStateMap.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
test('returns undefined if filtering by grading period and submission is not in any grading period', function() {
|
||||||
|
submissionStateMap = createAndSetupMap(assignment, options)
|
||||||
|
|
||||||
strictEqual(state.inNoGradingPeriod, true);
|
const state = submissionStateMap.getSubmissionState({
|
||||||
});
|
user_id: student.id,
|
||||||
|
assignment_id: assignment.id
|
||||||
|
})
|
||||||
|
|
||||||
test('returns false if submission has a grading period', function () {
|
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)
|
||||||
|
|
||||||
|
const state = submissionStateMap.getSubmissionState({
|
||||||
|
user_id: student.id,
|
||||||
|
assignment_id: assignment.id
|
||||||
|
})
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
const state = submissionStateMap.getSubmissionState({
|
||||||
|
user_id: student.id,
|
||||||
|
assignment_id: assignment.id
|
||||||
|
})
|
||||||
|
|
||||||
|
strictEqual(state.inOtherGradingPeriod, undefined)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
QUnit.module('inClosedGradingPeriod', function(hooks) {
|
||||||
|
hooks.beforeEach(() => {
|
||||||
|
assignment.effectiveDueDates[student.id] = {
|
||||||
|
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)
|
||||||
|
|
||||||
|
const state = submissionStateMap.getSubmissionState({
|
||||||
|
user_id: student.id,
|
||||||
|
assignment_id: assignment.id
|
||||||
|
})
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
const state = submissionStateMap.getSubmissionState({
|
||||||
|
user_id: student.id,
|
||||||
|
assignment_id: assignment.id
|
||||||
|
})
|
||||||
|
|
||||||
|
strictEqual(state.inClosedGradingPeriod, undefined)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
QUnit.module('SubmissionStateMap with grading periods', function(suiteHooks) {
|
||||||
|
const dueDate = '2015-07-15'
|
||||||
|
let assignment
|
||||||
|
let submissionStateMap
|
||||||
|
let options
|
||||||
|
|
||||||
|
suiteHooks.beforeEach(() => {
|
||||||
|
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() {
|
||||||
|
assignment.effectiveDueDates[student.id] = {
|
||||||
|
due_at: dueDate,
|
||||||
|
in_closed_grading_period: false
|
||||||
|
}
|
||||||
|
submissionStateMap = createAndSetupMap(assignment, options)
|
||||||
|
|
||||||
|
const state = submissionStateMap.getSubmissionState({
|
||||||
|
user_id: student.id,
|
||||||
|
assignment_id: assignment.id
|
||||||
|
})
|
||||||
|
|
||||||
|
strictEqual(state.inNoGradingPeriod, true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('returns false if submission has a grading period', function() {
|
||||||
assignment.effectiveDueDates[student.id] = {
|
assignment.effectiveDueDates[student.id] = {
|
||||||
due_at: dueDate,
|
due_at: dueDate,
|
||||||
grading_period_id: 1,
|
grading_period_id: 1,
|
||||||
in_closed_grading_period: false
|
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) {
|
QUnit.module('inOtherGradingPeriod', function(hooks) {
|
||||||
hooks.beforeEach(() => {
|
hooks.beforeEach(() => {
|
||||||
options = { hasGradingPeriods: true, selectedGradingPeriodID: '2' };
|
options = {hasGradingPeriods: true, selectedGradingPeriodID: '2'}
|
||||||
assignment.effectiveDueDates[student.id] = {
|
assignment.effectiveDueDates[student.id] = {
|
||||||
due_at: dueDate,
|
due_at: dueDate,
|
||||||
in_closed_grading_period: false
|
in_closed_grading_period: false
|
||||||
};
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
test('returns false if filtering by grading period and submission is not in any grading period', function () {
|
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 () {
|
test('returns true if filtering by grading period and submission is in another grading period', function() {
|
||||||
assignment.effectiveDueDates[student.id].grading_period_id = '1';
|
assignment.effectiveDueDates[student.id].grading_period_id = '1'
|
||||||
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, true);
|
strictEqual(state.inOtherGradingPeriod, true)
|
||||||
});
|
})
|
||||||
|
|
||||||
test('returns false if filtering by grading period and submission is in the same grading period', function () {
|
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';
|
assignment.effectiveDueDates[student.id].grading_period_id = '2'
|
||||||
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)
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
||||||
QUnit.module('inClosedGradingPeriod', function (hooks) {
|
QUnit.module('inClosedGradingPeriod', function(hooks) {
|
||||||
hooks.beforeEach(() => {
|
hooks.beforeEach(() => {
|
||||||
options = { hasGradingPeriods: true, selectedGradingPeriodID: '2' };
|
options = {hasGradingPeriods: true, selectedGradingPeriodID: '2'}
|
||||||
assignment.effectiveDueDates[student.id] = {
|
assignment.effectiveDueDates[student.id] = {
|
||||||
due_at: dueDate,
|
due_at: dueDate
|
||||||
};
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
test('returns true if submission is in a closed grading period', function () {
|
test('returns true if submission is in a closed grading period', function() {
|
||||||
assignment.effectiveDueDates[student.id].in_closed_grading_period = true;
|
assignment.effectiveDueDates[student.id].in_closed_grading_period = true
|
||||||
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.inClosedGradingPeriod, true);
|
strictEqual(state.inClosedGradingPeriod, true)
|
||||||
});
|
})
|
||||||
|
|
||||||
test('returns true if submission is in a closed grading period', function () {
|
test('returns true if submission is in a closed grading period', function() {
|
||||||
assignment.effectiveDueDates[student.id].in_closed_grading_period = false;
|
assignment.effectiveDueDates[student.id].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.inClosedGradingPeriod, false);
|
strictEqual(state.inClosedGradingPeriod, false)
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
|
@ -16,208 +16,218 @@
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* 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 = {
|
const student = {
|
||||||
id: '1',
|
id: '1',
|
||||||
group_ids: ['1'],
|
group_ids: ['1'],
|
||||||
sections: ['1']
|
sections: ['1']
|
||||||
};
|
}
|
||||||
|
|
||||||
function createMap (opts = {}) {
|
function createMap(opts = {}) {
|
||||||
const defaults = {
|
const defaults = {
|
||||||
hasGradingPeriods: false,
|
hasGradingPeriods: false,
|
||||||
selectedGradingPeriodID: '0',
|
selectedGradingPeriodID: '0',
|
||||||
isAdmin: false
|
isAdmin: false
|
||||||
};
|
}
|
||||||
|
|
||||||
const params = { ...defaults, ...opts };
|
const params = {...defaults, ...opts}
|
||||||
return new SubmissionStateMap(params);
|
return new SubmissionStateMap(params)
|
||||||
}
|
}
|
||||||
|
|
||||||
function createAndSetupMap (assignment, opts = {}) {
|
function createAndSetupMap(assignment, opts = {}) {
|
||||||
const map = createMap(opts);
|
const map = createMap(opts)
|
||||||
const assignments = {};
|
const assignments = {}
|
||||||
assignments[assignment.id] = assignment;
|
assignments[assignment.id] = assignment
|
||||||
map.setup([student], assignments);
|
map.setup([student], assignments)
|
||||||
return map;
|
return map
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: the spec setup above should live in a spec helper -- at the
|
// 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
|
// 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
|
// 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 () {
|
test('submission in an unpublished assignment is locked', function() {
|
||||||
const assignment = { id: '1', published: false, effectiveDueDates: {} };
|
const assignment = {id: '1', published: false, effectiveDueDates: {}}
|
||||||
const map = createAndSetupMap(assignment, { hasGradingPeriods: false });
|
const map = createAndSetupMap(assignment, {hasGradingPeriods: false})
|
||||||
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
|
||||||
strictEqual(state.locked, true);
|
strictEqual(state.locked, true)
|
||||||
});
|
})
|
||||||
|
|
||||||
test('submission in a published assignment is not locked', function () {
|
test('submission in a published assignment is not locked', function() {
|
||||||
const assignment = { id: '1', published: true, effectiveDueDates: {} };
|
const assignment = {id: '1', published: true, effectiveDueDates: {}}
|
||||||
const map = createAndSetupMap(assignment, { hasGradingPeriods: false });
|
const map = createAndSetupMap(assignment, {hasGradingPeriods: false})
|
||||||
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
|
||||||
strictEqual(state.locked, false);
|
strictEqual(state.locked, false)
|
||||||
});
|
})
|
||||||
|
|
||||||
test('submission is locked for a student without assignment visibility', function () {
|
test('submission is locked for a student without assignment visibility', function() {
|
||||||
const assignment = { id: '1', published: true, effectiveDueDates: {}, only_visible_to_overrides: true };
|
const assignment = {
|
||||||
const map = createAndSetupMap(assignment, { hasGradingPeriods: false });
|
id: '1',
|
||||||
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
published: true,
|
||||||
equal(state.locked, 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 () {
|
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] = {
|
assignment.effectiveDueDates[student.id] = {
|
||||||
due_at: null,
|
due_at: null,
|
||||||
grading_period_id: null,
|
grading_period_id: null,
|
||||||
in_closed_grading_period: false
|
in_closed_grading_period: false
|
||||||
};
|
}
|
||||||
|
|
||||||
const map = createAndSetupMap(assignment, { hasGradingPeriods: false });
|
const map = createAndSetupMap(assignment, {hasGradingPeriods: false})
|
||||||
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
|
||||||
equal(state.locked, false);
|
equal(state.locked, false)
|
||||||
});
|
})
|
||||||
|
|
||||||
QUnit.module('SubmissionStateMap with grading periods and all grading periods selected', {
|
QUnit.module('SubmissionStateMap with grading periods and all grading periods selected', {
|
||||||
setup () {
|
setup() {
|
||||||
this.DATE_IN_CLOSED_PERIOD = '2015-07-15';
|
this.DATE_IN_CLOSED_PERIOD = '2015-07-15'
|
||||||
this.DATE_NOT_IN_CLOSED_PERIOD = '2015-08-15';
|
this.DATE_NOT_IN_CLOSED_PERIOD = '2015-08-15'
|
||||||
this.mapOptions = { hasGradingPeriods: true, selectedGradingPeriodID: '0' };
|
this.mapOptions = {hasGradingPeriods: true, selectedGradingPeriodID: '0'}
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
test('submission is locked for a student without assignment visibility', function () {
|
test('submission is locked for a student without assignment visibility', function() {
|
||||||
const assignment = { id: '1', published: true, effectiveDueDates: {}, only_visible_to_overrides: true };
|
const assignment = {
|
||||||
const map = createAndSetupMap(assignment, this.mapOptions);
|
id: '1',
|
||||||
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
published: true,
|
||||||
equal(state.locked, 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 () {
|
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] = {
|
assignment.effectiveDueDates[student.id] = {
|
||||||
due_at: this.DATE_IN_CLOSED_PERIOD,
|
due_at: this.DATE_IN_CLOSED_PERIOD,
|
||||||
grading_period_id: '1',
|
grading_period_id: '1',
|
||||||
in_closed_grading_period: true
|
in_closed_grading_period: true
|
||||||
};
|
}
|
||||||
|
|
||||||
const map = createAndSetupMap(assignment, this.mapOptions);
|
const map = createAndSetupMap(assignment, this.mapOptions)
|
||||||
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
|
||||||
equal(state.locked, true);
|
equal(state.locked, true)
|
||||||
});
|
})
|
||||||
|
|
||||||
test('user is admin: submission is unlocked for an assigned student with assignment due in a closed grading period', function () {
|
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] = {
|
assignment.effectiveDueDates[student.id] = {
|
||||||
due_at: this.DATE_IN_CLOSED_PERIOD,
|
due_at: this.DATE_IN_CLOSED_PERIOD,
|
||||||
grading_period_id: '1',
|
grading_period_id: '1',
|
||||||
in_closed_grading_period: true
|
in_closed_grading_period: true
|
||||||
};
|
}
|
||||||
|
|
||||||
const mapOptions = { ...this.mapOptions, isAdmin: true };
|
const mapOptions = {...this.mapOptions, isAdmin: true}
|
||||||
const map = createAndSetupMap(assignment, mapOptions);
|
const map = createAndSetupMap(assignment, mapOptions)
|
||||||
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
|
||||||
equal(state.locked, false);
|
equal(state.locked, false)
|
||||||
});
|
})
|
||||||
|
|
||||||
test('submission is unlocked for an assigned student with assignment due outside of a closed grading period', function () {
|
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] = {
|
assignment.effectiveDueDates[student.id] = {
|
||||||
due_at: this.DATE_NOT_IN_CLOSED_PERIOD,
|
due_at: this.DATE_NOT_IN_CLOSED_PERIOD,
|
||||||
grading_period_id: '1',
|
grading_period_id: '1',
|
||||||
in_closed_grading_period: false
|
in_closed_grading_period: false
|
||||||
};
|
}
|
||||||
|
|
||||||
const map = createAndSetupMap(assignment, this.mapOptions);
|
const map = createAndSetupMap(assignment, this.mapOptions)
|
||||||
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
|
||||||
equal(state.locked, false);
|
equal(state.locked, false)
|
||||||
});
|
})
|
||||||
|
|
||||||
QUnit.module('SubmissionStateMap with grading periods and a non-closed grading period selected', {
|
QUnit.module('SubmissionStateMap with grading periods and a non-closed grading period selected', {
|
||||||
setup () {
|
setup() {
|
||||||
this.DATE_IN_SELECTED_PERIOD = '2015-07-15';
|
this.DATE_IN_SELECTED_PERIOD = '2015-07-15'
|
||||||
this.DATE_NOT_IN_SELECTED_PERIOD = '2015-08-15';
|
this.DATE_NOT_IN_SELECTED_PERIOD = '2015-08-15'
|
||||||
this.SELECTED_PERIOD_ID = '1';
|
this.SELECTED_PERIOD_ID = '1'
|
||||||
this.mapOptions = { hasGradingPeriods: true, selectedGradingPeriodID: this.SELECTED_PERIOD_ID };
|
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 () {
|
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] = {
|
assignment.effectiveDueDates[student.id] = {
|
||||||
due_at: this.DATE_NOT_IN_SELECTED_PERIOD,
|
due_at: this.DATE_NOT_IN_SELECTED_PERIOD,
|
||||||
grading_period_id: '2',
|
grading_period_id: '2',
|
||||||
in_closed_grading_period: false
|
in_closed_grading_period: false
|
||||||
};
|
}
|
||||||
|
|
||||||
const map = createAndSetupMap(assignment, this.mapOptions);
|
const map = createAndSetupMap(assignment, this.mapOptions)
|
||||||
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
|
||||||
equal(state.locked, true);
|
equal(state.locked, true)
|
||||||
});
|
})
|
||||||
|
|
||||||
test('submission is unlocked for an assigned student with assignment due in the selected grading period', function () {
|
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] = {
|
assignment.effectiveDueDates[student.id] = {
|
||||||
due_at: this.DATE_IN_SELECTED_PERIOD,
|
due_at: this.DATE_IN_SELECTED_PERIOD,
|
||||||
grading_period_id: this.SELECTED_PERIOD_ID,
|
grading_period_id: this.SELECTED_PERIOD_ID,
|
||||||
in_closed_grading_period: false
|
in_closed_grading_period: false
|
||||||
};
|
}
|
||||||
|
|
||||||
const map = createAndSetupMap(assignment, this.mapOptions);
|
const map = createAndSetupMap(assignment, this.mapOptions)
|
||||||
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
|
||||||
equal(state.locked, false);
|
equal(state.locked, false)
|
||||||
});
|
})
|
||||||
|
|
||||||
QUnit.module('SubmissionStateMap with grading periods and a closed grading period selected', {
|
QUnit.module('SubmissionStateMap with grading periods and a closed grading period selected', {
|
||||||
setup () {
|
setup() {
|
||||||
this.DATE_IN_SELECTED_PERIOD = '2015-07-15';
|
this.DATE_IN_SELECTED_PERIOD = '2015-07-15'
|
||||||
this.DATE_NOT_IN_SELECTED_PERIOD = '2015-08-15';
|
this.DATE_NOT_IN_SELECTED_PERIOD = '2015-08-15'
|
||||||
this.SELECTED_PERIOD_ID = '1';
|
this.SELECTED_PERIOD_ID = '1'
|
||||||
this.mapOptions = { hasGradingPeriods: true, selectedGradingPeriodID: this.SELECTED_PERIOD_ID };
|
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 () {
|
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] = {
|
assignment.effectiveDueDates[student.id] = {
|
||||||
due_at: this.DATE_NOT_IN_SELECTED_PERIOD,
|
due_at: this.DATE_NOT_IN_SELECTED_PERIOD,
|
||||||
grading_period_id: '2',
|
grading_period_id: '2',
|
||||||
in_closed_grading_period: false
|
in_closed_grading_period: false
|
||||||
};
|
}
|
||||||
|
|
||||||
const map = createAndSetupMap(assignment, this.mapOptions);
|
const map = createAndSetupMap(assignment, this.mapOptions)
|
||||||
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
|
||||||
equal(state.locked, true);
|
equal(state.locked, true)
|
||||||
});
|
})
|
||||||
|
|
||||||
test('submission is locked for an assigned student with assignment due in the selected grading period', function () {
|
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] = {
|
assignment.effectiveDueDates[student.id] = {
|
||||||
due_at: this.DATE_IN_SELECTED_PERIOD,
|
due_at: this.DATE_IN_SELECTED_PERIOD,
|
||||||
grading_period_id: this.SELECTED_PERIOD_ID,
|
grading_period_id: this.SELECTED_PERIOD_ID,
|
||||||
in_closed_grading_period: true
|
in_closed_grading_period: true
|
||||||
};
|
}
|
||||||
|
|
||||||
const map = createAndSetupMap(assignment, this.mapOptions);
|
const map = createAndSetupMap(assignment, this.mapOptions)
|
||||||
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
|
||||||
equal(state.locked, true);
|
equal(state.locked, true)
|
||||||
});
|
})
|
||||||
|
|
||||||
test('user is admin: submission is unlocked for an assigned student with assignment due in the selected grading period', function () {
|
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] = {
|
assignment.effectiveDueDates[student.id] = {
|
||||||
due_at: this.DATE_IN_SELECTED_PERIOD,
|
due_at: this.DATE_IN_SELECTED_PERIOD,
|
||||||
grading_period_id: this.SELECTED_PERIOD_ID,
|
grading_period_id: this.SELECTED_PERIOD_ID,
|
||||||
in_closed_grading_period: true
|
in_closed_grading_period: true
|
||||||
};
|
}
|
||||||
|
|
||||||
const mapOptions = { ...this.mapOptions, isAdmin: true };
|
const mapOptions = {...this.mapOptions, isAdmin: true}
|
||||||
const map = createAndSetupMap(assignment, mapOptions);
|
const map = createAndSetupMap(assignment, mapOptions)
|
||||||
const state = map.getSubmissionState({ user_id: student.id, assignment_id: assignment.id });
|
const state = map.getSubmissionState({user_id: student.id, assignment_id: assignment.id})
|
||||||
equal(state.locked, false);
|
equal(state.locked, false)
|
||||||
});
|
})
|
||||||
|
|
|
@ -16,30 +16,32 @@
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {fromJS} from 'immutable';
|
import {fromJS} from 'immutable'
|
||||||
import moment from 'moment';
|
import moment from 'moment'
|
||||||
import SubmissionStateMap from 'jsx/gradezilla/SubmissionStateMap';
|
import SubmissionStateMap from 'jsx/gradezilla/SubmissionStateMap'
|
||||||
|
|
||||||
const studentWithoutSubmission = {
|
const studentWithoutSubmission = {
|
||||||
id: '1',
|
id: '1',
|
||||||
group_ids: ['1'],
|
group_ids: ['1'],
|
||||||
sections: ['1']
|
sections: ['1']
|
||||||
};
|
}
|
||||||
|
|
||||||
const studentWithSubmission = {
|
const studentWithSubmission = {
|
||||||
id: '1',
|
id: '1',
|
||||||
group_ids: ['1'],
|
group_ids: ['1'],
|
||||||
sections: ['1'],
|
sections: ['1'],
|
||||||
assignment_1: {}
|
assignment_1: {}
|
||||||
};
|
}
|
||||||
|
|
||||||
const yesterday = moment(new Date()).subtract(1, 'day');
|
const yesterday = moment(new Date()).subtract(1, 'day')
|
||||||
const tomorrow = moment(new Date()).add(1, 'day');
|
const tomorrow = moment(new Date()).add(1, 'day')
|
||||||
|
|
||||||
const baseAssignment = fromJS({
|
const baseAssignment = fromJS({
|
||||||
id: '1',
|
id: '1',
|
||||||
published: true,
|
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 unpublishedAssignment = baseAssignment.merge({published: false})
|
||||||
const anonymousMutedAssignment = baseAssignment.merge({
|
const anonymousMutedAssignment = baseAssignment.merge({
|
||||||
|
@ -47,29 +49,33 @@ const anonymousMutedAssignment = baseAssignment.merge({
|
||||||
anonymous_grading: true,
|
anonymous_grading: true,
|
||||||
muted: true
|
muted: true
|
||||||
})
|
})
|
||||||
const moderatedAndGradesUnpublishedAssignment =
|
const moderatedAndGradesUnpublishedAssignment = baseAssignment.merge({
|
||||||
baseAssignment.merge({moderated_grading: true, grades_published: false})
|
moderated_grading: true,
|
||||||
const hiddenFromStudent =
|
grades_published: false
|
||||||
baseAssignment.merge({only_visible_to_overrides: true, assignment_visibility: []})
|
})
|
||||||
|
const hiddenFromStudent = baseAssignment.merge({
|
||||||
|
only_visible_to_overrides: true,
|
||||||
|
assignment_visibility: []
|
||||||
|
})
|
||||||
const hasGradingPeriodsAssignment = baseAssignment
|
const hasGradingPeriodsAssignment = baseAssignment
|
||||||
|
|
||||||
function createMap (opts = {}) {
|
function createMap(opts = {}) {
|
||||||
const defaults = {
|
const defaults = {
|
||||||
hasGradingPeriods: false,
|
hasGradingPeriods: false,
|
||||||
selectedGradingPeriodID: '0',
|
selectedGradingPeriodID: '0',
|
||||||
isAdmin: false
|
isAdmin: false
|
||||||
};
|
}
|
||||||
|
|
||||||
const params = { ...defaults, ...opts };
|
const params = {...defaults, ...opts}
|
||||||
return new SubmissionStateMap(params);
|
return new SubmissionStateMap(params)
|
||||||
}
|
}
|
||||||
|
|
||||||
function createAndSetupMap (assignment, student, opts = {}) {
|
function createAndSetupMap(assignment, student, opts = {}) {
|
||||||
const map = createMap(opts);
|
const map = createMap(opts)
|
||||||
const assignments = {};
|
const assignments = {}
|
||||||
assignments[assignment.id] = assignment;
|
assignments[assignment.id] = assignment
|
||||||
map.setup([student], assignments);
|
map.setup([student], assignments)
|
||||||
return map;
|
return map
|
||||||
}
|
}
|
||||||
|
|
||||||
QUnit.module('#setSubmissionCellState', function() {
|
QUnit.module('#setSubmissionCellState', function() {
|
||||||
|
@ -77,21 +83,27 @@ QUnit.module('#setSubmissionCellState', function() {
|
||||||
const assignment = {
|
const assignment = {
|
||||||
id: '1',
|
id: '1',
|
||||||
published: false
|
published: false
|
||||||
};
|
}
|
||||||
const map = createAndSetupMap(assignment, studentWithSubmission);
|
const map = createAndSetupMap(assignment, studentWithSubmission)
|
||||||
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
|
const submission = map.getSubmissionState({
|
||||||
strictEqual(submission.locked, true);
|
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() {
|
test('the submission state has hideGrade set if assignment is not published', function() {
|
||||||
const assignment = {
|
const assignment = {
|
||||||
id: '1',
|
id: '1',
|
||||||
published: false
|
published: false
|
||||||
};
|
}
|
||||||
const map = createAndSetupMap(assignment, studentWithSubmission);
|
const map = createAndSetupMap(assignment, studentWithSubmission)
|
||||||
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
|
const submission = map.getSubmissionState({
|
||||||
strictEqual(submission.hideGrade, true);
|
user_id: studentWithSubmission.id,
|
||||||
});
|
assignment_id: assignment.id
|
||||||
|
})
|
||||||
|
strictEqual(submission.hideGrade, true)
|
||||||
|
})
|
||||||
|
|
||||||
test('the submission state is locked if assignment is not visible', function() {
|
test('the submission state is locked if assignment is not visible', function() {
|
||||||
const assignment = {
|
const assignment = {
|
||||||
|
@ -99,11 +111,14 @@ QUnit.module('#setSubmissionCellState', function() {
|
||||||
published: true,
|
published: true,
|
||||||
only_visible_to_overrides: true,
|
only_visible_to_overrides: true,
|
||||||
assignment_visibility: []
|
assignment_visibility: []
|
||||||
};
|
}
|
||||||
const map = createAndSetupMap(assignment, studentWithSubmission);
|
const map = createAndSetupMap(assignment, studentWithSubmission)
|
||||||
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
|
const submission = map.getSubmissionState({
|
||||||
strictEqual(submission.locked, true);
|
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() {
|
test('the submission state has hideGrade set if assignment is not visible', function() {
|
||||||
const assignment = {
|
const assignment = {
|
||||||
|
@ -111,33 +126,42 @@ QUnit.module('#setSubmissionCellState', function() {
|
||||||
published: true,
|
published: true,
|
||||||
only_visible_to_overrides: true,
|
only_visible_to_overrides: true,
|
||||||
assignment_visibility: []
|
assignment_visibility: []
|
||||||
};
|
}
|
||||||
const map = createAndSetupMap(assignment, studentWithSubmission);
|
const map = createAndSetupMap(assignment, studentWithSubmission)
|
||||||
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
|
const submission = map.getSubmissionState({
|
||||||
strictEqual(submission.hideGrade, true);
|
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() {
|
test('the submission state is not locked if assignment is published and visible', function() {
|
||||||
const assignment = {
|
const assignment = {
|
||||||
id: '1',
|
id: '1',
|
||||||
published: true,
|
published: true,
|
||||||
only_visible_to_overrides: false
|
only_visible_to_overrides: false
|
||||||
};
|
}
|
||||||
const map = createAndSetupMap(assignment, studentWithSubmission);
|
const map = createAndSetupMap(assignment, studentWithSubmission)
|
||||||
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
|
const submission = map.getSubmissionState({
|
||||||
strictEqual(submission.locked, false);
|
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() {
|
test('the submission state has hideGrade not set if assignment is published and visible', function() {
|
||||||
const assignment = {
|
const assignment = {
|
||||||
id: '1',
|
id: '1',
|
||||||
published: true,
|
published: true,
|
||||||
only_visible_to_overrides: false
|
only_visible_to_overrides: false
|
||||||
};
|
}
|
||||||
const map = createAndSetupMap(assignment, studentWithSubmission);
|
const map = createAndSetupMap(assignment, studentWithSubmission)
|
||||||
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
|
const submission = map.getSubmissionState({
|
||||||
strictEqual(submission.hideGrade, false);
|
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() {
|
test('the submission state is locked when the student is not assigned', function() {
|
||||||
const assignment = {
|
const assignment = {
|
||||||
|
@ -147,7 +171,10 @@ QUnit.module('#setSubmissionCellState', function() {
|
||||||
assignment_visibility: ['2']
|
assignment_visibility: ['2']
|
||||||
}
|
}
|
||||||
const map = createAndSetupMap(assignment, studentWithSubmission)
|
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)
|
strictEqual(submission.locked, true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -156,22 +183,28 @@ QUnit.module('#setSubmissionCellState', function() {
|
||||||
id: '1',
|
id: '1',
|
||||||
published: true,
|
published: true,
|
||||||
moderated_grading: false
|
moderated_grading: false
|
||||||
};
|
}
|
||||||
const map = createAndSetupMap(assignment, studentWithSubmission);
|
const map = createAndSetupMap(assignment, studentWithSubmission)
|
||||||
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
|
const submission = map.getSubmissionState({
|
||||||
strictEqual(submission.locked, false);
|
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() {
|
test('the submission state has hideGrade not set if not moderated grading', function() {
|
||||||
const assignment = {
|
const assignment = {
|
||||||
id: '1',
|
id: '1',
|
||||||
published: true,
|
published: true,
|
||||||
moderated_grading: false
|
moderated_grading: false
|
||||||
};
|
}
|
||||||
const map = createAndSetupMap(assignment, studentWithSubmission);
|
const map = createAndSetupMap(assignment, studentWithSubmission)
|
||||||
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
|
const submission = map.getSubmissionState({
|
||||||
strictEqual(submission.hideGrade, false);
|
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() {
|
test('the submission state is not locked if moderated grading and grades published', function() {
|
||||||
const assignment = {
|
const assignment = {
|
||||||
|
@ -179,11 +212,14 @@ QUnit.module('#setSubmissionCellState', function() {
|
||||||
published: true,
|
published: true,
|
||||||
moderated_grading: true,
|
moderated_grading: true,
|
||||||
grades_published: true
|
grades_published: true
|
||||||
};
|
}
|
||||||
const map = createAndSetupMap(assignment, studentWithSubmission);
|
const map = createAndSetupMap(assignment, studentWithSubmission)
|
||||||
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
|
const submission = map.getSubmissionState({
|
||||||
strictEqual(submission.locked, false);
|
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() {
|
test('the submission state has hideGrade not set if moderated grading and grades published', function() {
|
||||||
const assignment = {
|
const assignment = {
|
||||||
|
@ -191,11 +227,14 @@ QUnit.module('#setSubmissionCellState', function() {
|
||||||
published: true,
|
published: true,
|
||||||
moderated_grading: true,
|
moderated_grading: true,
|
||||||
grades_published: true
|
grades_published: true
|
||||||
};
|
}
|
||||||
const map = createAndSetupMap(assignment, studentWithSubmission);
|
const map = createAndSetupMap(assignment, studentWithSubmission)
|
||||||
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
|
const submission = map.getSubmissionState({
|
||||||
strictEqual(submission.hideGrade, false);
|
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() {
|
test('the submission state is locked if moderated grading and grades not published', function() {
|
||||||
const assignment = {
|
const assignment = {
|
||||||
|
@ -203,11 +242,14 @@ QUnit.module('#setSubmissionCellState', function() {
|
||||||
published: true,
|
published: true,
|
||||||
moderated_grading: true,
|
moderated_grading: true,
|
||||||
grades_published: false
|
grades_published: false
|
||||||
};
|
}
|
||||||
const map = createAndSetupMap(assignment, studentWithSubmission);
|
const map = createAndSetupMap(assignment, studentWithSubmission)
|
||||||
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
|
const submission = map.getSubmissionState({
|
||||||
strictEqual(submission.locked, true);
|
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() {
|
test('the submission state has hideGrade not set if moderated grading and grades not published', function() {
|
||||||
const assignment = {
|
const assignment = {
|
||||||
|
@ -215,114 +257,132 @@ QUnit.module('#setSubmissionCellState', function() {
|
||||||
published: true,
|
published: true,
|
||||||
moderated_grading: true,
|
moderated_grading: true,
|
||||||
grades_published: false
|
grades_published: false
|
||||||
};
|
}
|
||||||
const map = createAndSetupMap(assignment, studentWithSubmission);
|
const map = createAndSetupMap(assignment, studentWithSubmission)
|
||||||
const submission = map.getSubmissionState({ user_id: studentWithSubmission.id, assignment_id: assignment.id });
|
const submission = map.getSubmissionState({
|
||||||
strictEqual(submission.hideGrade, false);
|
user_id: studentWithSubmission.id,
|
||||||
});
|
assignment_id: assignment.id
|
||||||
|
})
|
||||||
|
strictEqual(submission.hideGrade, false)
|
||||||
|
})
|
||||||
|
|
||||||
QUnit.module('when the assignment is anonymous', function(hooks) {
|
QUnit.module('when the assignment is anonymous', function(hooks) {
|
||||||
let assignment
|
let assignment
|
||||||
|
|
||||||
hooks.beforeEach(() => {
|
hooks.beforeEach(() => {
|
||||||
assignment = { id: '1', published: true, anonymous_grading: true }
|
assignment = {id: '1', published: true, anonymous_grading: true}
|
||||||
})
|
})
|
||||||
|
|
||||||
test('the submission state is locked when anonymize_students is true', function() {
|
test('the submission state is locked when anonymize_students is true', function() {
|
||||||
assignment.anonymize_students = true
|
assignment.anonymize_students = true
|
||||||
const map = createAndSetupMap(assignment, studentWithSubmission)
|
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)
|
strictEqual(submission.locked, true)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('the submission state is hidden when anonymize_students is true', function() {
|
test('the submission state is hidden when anonymize_students is true', function() {
|
||||||
assignment.anonymize_students = true
|
assignment.anonymize_students = true
|
||||||
const map = createAndSetupMap(assignment, studentWithSubmission)
|
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)
|
strictEqual(submission.hideGrade, true)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('the submission state is unlocked when the assignment is unmuted', function() {
|
test('the submission state is unlocked when the assignment is unmuted', function() {
|
||||||
const map = createAndSetupMap(assignment, studentWithSubmission)
|
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)
|
strictEqual(submission.locked, false)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('the submission state is not hidden when the assignment is unmuted', function() {
|
test('the submission state is not hidden when the assignment is unmuted', function() {
|
||||||
const map = createAndSetupMap(assignment, studentWithSubmission)
|
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)
|
strictEqual(submission.hideGrade, false)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
QUnit.module('no submission', function() {
|
QUnit.module('no submission', function() {
|
||||||
test('the submission object is missing if the assignment is late', function () {
|
test('the submission object is missing if the assignment is late', function() {
|
||||||
const assignment = {
|
const assignment = {
|
||||||
id: '1',
|
id: '1',
|
||||||
published: true,
|
published: true,
|
||||||
effectiveDueDates: { 1: { due_at: yesterday } }
|
effectiveDueDates: {1: {due_at: yesterday}}
|
||||||
};
|
}
|
||||||
const map = createAndSetupMap(assignment, studentWithoutSubmission);
|
const map = createAndSetupMap(assignment, studentWithoutSubmission)
|
||||||
const submission = map.getSubmission(studentWithoutSubmission.id, assignment.id);
|
const submission = map.getSubmission(studentWithoutSubmission.id, assignment.id)
|
||||||
strictEqual(submission.missing, true);
|
strictEqual(submission.missing, true)
|
||||||
});
|
})
|
||||||
|
|
||||||
test('the submission object is not missing if the assignment is not late', function () {
|
test('the submission object is not missing if the assignment is not late', function() {
|
||||||
const assignment = {
|
const assignment = {
|
||||||
id: '1',
|
id: '1',
|
||||||
published: true,
|
published: true,
|
||||||
effectiveDueDates: { 1: { due_at: tomorrow } }
|
effectiveDueDates: {1: {due_at: tomorrow}}
|
||||||
};
|
}
|
||||||
const map = createAndSetupMap(assignment, studentWithoutSubmission);
|
const map = createAndSetupMap(assignment, studentWithoutSubmission)
|
||||||
const submission = map.getSubmission(studentWithoutSubmission.id, assignment.id);
|
const submission = map.getSubmission(studentWithoutSubmission.id, assignment.id)
|
||||||
strictEqual(submission.missing, false);
|
strictEqual(submission.missing, false)
|
||||||
});
|
})
|
||||||
|
|
||||||
test('the submission object is not missing, if the assignment is not late ' +
|
test(
|
||||||
'and there are no due dates', function () {
|
'the submission object is not missing, if the assignment is not late ' +
|
||||||
const assignment = {
|
'and there are no due dates',
|
||||||
id: '1',
|
function() {
|
||||||
published: true,
|
const assignment = {
|
||||||
effectiveDueDates: {}
|
id: '1',
|
||||||
};
|
published: true,
|
||||||
const map = createAndSetupMap(assignment, studentWithoutSubmission);
|
effectiveDueDates: {}
|
||||||
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 () {
|
test('the submission object has seconds_late set to zero', function() {
|
||||||
const assignment = {
|
const assignment = {
|
||||||
id: '1',
|
id: '1',
|
||||||
published: true,
|
published: true,
|
||||||
effectiveDueDates: { 1: { due_at: new Date() } }
|
effectiveDueDates: {1: {due_at: new Date()}}
|
||||||
};
|
}
|
||||||
const map = createAndSetupMap(assignment, studentWithoutSubmission);
|
const map = createAndSetupMap(assignment, studentWithoutSubmission)
|
||||||
const submission = map.getSubmission(studentWithoutSubmission.id, assignment.id);
|
const submission = map.getSubmission(studentWithoutSubmission.id, assignment.id)
|
||||||
strictEqual(submission.seconds_late, 0);
|
strictEqual(submission.seconds_late, 0)
|
||||||
});
|
})
|
||||||
|
|
||||||
test('the submission object has late set to false', function () {
|
test('the submission object has late set to false', function() {
|
||||||
const assignment = {
|
const assignment = {
|
||||||
id: '1',
|
id: '1',
|
||||||
published: true,
|
published: true,
|
||||||
effectiveDueDates: { 1: { due_at: new Date() } }
|
effectiveDueDates: {1: {due_at: new Date()}}
|
||||||
};
|
}
|
||||||
const map = createAndSetupMap(assignment, studentWithoutSubmission);
|
const map = createAndSetupMap(assignment, studentWithoutSubmission)
|
||||||
const submission = map.getSubmission(studentWithoutSubmission.id, assignment.id);
|
const submission = map.getSubmission(studentWithoutSubmission.id, assignment.id)
|
||||||
strictEqual(submission.late, false);
|
strictEqual(submission.late, false)
|
||||||
});
|
})
|
||||||
|
|
||||||
test('the submission object has excused set to false', function () {
|
test('the submission object has excused set to false', function() {
|
||||||
const assignment = {
|
const assignment = {
|
||||||
id: '1',
|
id: '1',
|
||||||
published: true,
|
published: true,
|
||||||
effectiveDueDates: { 1: { due_at: new Date() } }
|
effectiveDueDates: {1: {due_at: new Date()}}
|
||||||
};
|
}
|
||||||
const map = createAndSetupMap(assignment, studentWithoutSubmission);
|
const map = createAndSetupMap(assignment, studentWithoutSubmission)
|
||||||
const submission = map.getSubmission(studentWithoutSubmission.id, assignment.id);
|
const submission = map.getSubmission(studentWithoutSubmission.id, assignment.id)
|
||||||
strictEqual(submission.excused, false);
|
strictEqual(submission.excused, false)
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
||||||
test('an unpublished assignment is locked and grades are hidden', () => {
|
test('an unpublished assignment is locked and grades are hidden', () => {
|
||||||
const map = createAndSetupMap(unpublishedAssignment.toJS(), studentWithoutSubmission)
|
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', () => {
|
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({
|
const submission = map.getSubmissionState({
|
||||||
user_id: studentWithoutSubmission.id,
|
user_id: studentWithoutSubmission.id,
|
||||||
assignment_id: moderatedAndGradesUnpublishedAssignment.get('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', () => {
|
test('is unpublished takes precedence over one that is moderated and has unpublished grades', () => {
|
||||||
const assignment = moderatedAndGradesUnpublishedAssignment.merge(unpublishedAssignment)
|
const assignment = moderatedAndGradesUnpublishedAssignment.merge(unpublishedAssignment)
|
||||||
const map = createAndSetupMap(assignment.toJS(), studentWithSubmission)
|
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})
|
deepEqual(submission, {locked: true, hideGrade: true})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('is anonymously graded and muted takes precedence over one that is moderated and has unpublished grades', () => {
|
test('is anonymously graded and muted takes precedence over one that is moderated and has unpublished grades', () => {
|
||||||
const assignment = moderatedAndGradesUnpublishedAssignment.merge(anonymousMutedAssignment)
|
const assignment = moderatedAndGradesUnpublishedAssignment.merge(anonymousMutedAssignment)
|
||||||
const map = createAndSetupMap(assignment.toJS(), studentWithSubmission)
|
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})
|
deepEqual(submission, {locked: true, hideGrade: true})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('is moderated and has unpublished grades takes precedence over one that is hidden from the student', () => {
|
test('is moderated and has unpublished grades takes precedence over one that is hidden from the student', () => {
|
||||||
const assignment = hiddenFromStudent.merge(moderatedAndGradesUnpublishedAssignment)
|
const assignment = hiddenFromStudent.merge(moderatedAndGradesUnpublishedAssignment)
|
||||||
const map = createAndSetupMap(assignment.toJS(), studentWithSubmission)
|
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})
|
deepEqual(submission, {locked: true, hideGrade: false})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('is hidden from the student takes precendence over one that has grading periods', () => {
|
test('is hidden from the student takes precendence over one that has grading periods', () => {
|
||||||
const assignment = hasGradingPeriodsAssignment.merge(hiddenFromStudent)
|
const assignment = hasGradingPeriodsAssignment.merge(hiddenFromStudent)
|
||||||
const map = createAndSetupMap(assignment.toJS(), studentWithSubmission, {hasGradingPeriods: true})
|
const map = createAndSetupMap(assignment.toJS(), studentWithSubmission, {
|
||||||
const submission = map.getSubmissionState({user_id: studentWithSubmission.id, assignment_id: assignment.get('id')})
|
hasGradingPeriods: true
|
||||||
|
})
|
||||||
|
const submission = map.getSubmissionState({
|
||||||
|
user_id: studentWithSubmission.id,
|
||||||
|
assignment_id: assignment.get('id')
|
||||||
|
})
|
||||||
deepEqual(submission, {locked: true, hideGrade: true})
|
deepEqual(submission, {locked: true, hideGrade: true})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('has grading periods takes precendence over all other assignments', () => {
|
test('has grading periods takes precendence over all other assignments', () => {
|
||||||
const assignment = hasGradingPeriodsAssignment.merge(baseAssignment)
|
const assignment = hasGradingPeriodsAssignment.merge(baseAssignment)
|
||||||
const map = createAndSetupMap(assignment.toJS(), studentWithSubmission, {hasGradingPeriods: true})
|
const map = createAndSetupMap(assignment.toJS(), studentWithSubmission, {
|
||||||
const actualSubmissionState = map.getSubmissionState({user_id: studentWithSubmission.id, assignment_id: assignment.get('id')})
|
hasGradingPeriods: true
|
||||||
|
})
|
||||||
|
const actualSubmissionState = map.getSubmissionState({
|
||||||
|
user_id: studentWithSubmission.id,
|
||||||
|
assignment_id: assignment.get('id')
|
||||||
|
})
|
||||||
const expectedSubmissionState = {
|
const expectedSubmissionState = {
|
||||||
locked: true,
|
locked: true,
|
||||||
hideGrade: false,
|
hideGrade: false,
|
||||||
|
@ -407,4 +489,4 @@ QUnit.module('#setSubmissionCellState', function() {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
});
|
})
|
||||||
|
|
|
@ -22,11 +22,12 @@ define([
|
||||||
'jsx/gradezilla/default_gradebook/CurveGradesDialogManager',
|
'jsx/gradezilla/default_gradebook/CurveGradesDialogManager',
|
||||||
'i18n!gradebook',
|
'i18n!gradebook',
|
||||||
'compiled/jquery.rails_flash_notifications'
|
'compiled/jquery.rails_flash_notifications'
|
||||||
], ($, CurveGradesDialog, { createCurveGradesAction }, I18n) => {
|
], ($, CurveGradesDialog, {createCurveGradesAction}, I18n) => {
|
||||||
QUnit.module('CurveGradesDialogManager.createCurveGradesAction.isDisabled', {
|
QUnit.module('CurveGradesDialogManager.createCurveGradesAction.isDisabled', {
|
||||||
props ({points_possible, grading_type, submissionsLoaded}) {
|
props({points_possible, grading_type, submissionsLoaded}) {
|
||||||
return [
|
return [
|
||||||
{ // assignment
|
{
|
||||||
|
// assignment
|
||||||
points_possible,
|
points_possible,
|
||||||
grading_type
|
grading_type
|
||||||
},
|
},
|
||||||
|
@ -36,47 +37,73 @@ define([
|
||||||
contextUrl: 'http://contextUrl/',
|
contextUrl: 'http://contextUrl/',
|
||||||
submissionsLoaded
|
submissionsLoaded
|
||||||
}
|
}
|
||||||
];
|
]
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
test('is not disabled when submissions are loaded, grading type is not pass/fail and there are ' +
|
test(
|
||||||
'points that are not 0', function () {
|
'is not disabled when submissions are loaded, grading type is not pass/fail and there are ' +
|
||||||
const props = this.props({points_possible: 10, grading_type: 'points', submissionsLoaded: true});
|
'points that are not 0',
|
||||||
notOk(createCurveGradesAction(...props).isDisabled);
|
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 () {
|
test('is disabled when submissions are not loaded', function() {
|
||||||
const props = this.props({points_possible: 10, grading_type: 'points', submissionsLoaded: false });
|
const props = this.props({
|
||||||
ok(createCurveGradesAction(...props).isDisabled);
|
points_possible: 10,
|
||||||
});
|
grading_type: 'points',
|
||||||
|
submissionsLoaded: false
|
||||||
|
})
|
||||||
|
ok(createCurveGradesAction(...props).isDisabled)
|
||||||
|
})
|
||||||
|
|
||||||
test('is disabled when grading type is pass/fail', function () {
|
test('is disabled when grading type is pass/fail', function() {
|
||||||
const props = this.props({points_possible: 10, grading_type: 'pass_fail', submissionsLoaded: true });
|
const props = this.props({
|
||||||
ok(createCurveGradesAction(...props).isDisabled);
|
points_possible: 10,
|
||||||
});
|
grading_type: 'pass_fail',
|
||||||
|
submissionsLoaded: true
|
||||||
|
})
|
||||||
|
ok(createCurveGradesAction(...props).isDisabled)
|
||||||
|
})
|
||||||
|
|
||||||
test('returns true when points_possible is null', function () {
|
test('returns true when points_possible is null', function() {
|
||||||
const props = this.props({points_possible: null, grading_type: 'points', submissionsLoaded: true});
|
const props = this.props({
|
||||||
ok(createCurveGradesAction(...props).isDisabled);
|
points_possible: null,
|
||||||
});
|
grading_type: 'points',
|
||||||
|
submissionsLoaded: true
|
||||||
|
})
|
||||||
|
ok(createCurveGradesAction(...props).isDisabled)
|
||||||
|
})
|
||||||
|
|
||||||
test('returns true when points_possible is 0', function () {
|
test('returns true when points_possible is 0', function() {
|
||||||
const props = this.props({points_possible: 0, grading_type: 'points', submissionsLoaded: true});
|
const props = this.props({points_possible: 0, grading_type: 'points', submissionsLoaded: true})
|
||||||
ok(createCurveGradesAction(...props).isDisabled);
|
ok(createCurveGradesAction(...props).isDisabled)
|
||||||
});
|
})
|
||||||
|
|
||||||
QUnit.module('CurveGradesDialogManager.createCurveGradesAction.onSelect', {
|
QUnit.module('CurveGradesDialogManager.createCurveGradesAction.onSelect', {
|
||||||
setup () {
|
setup() {
|
||||||
this.flashErrorSpy = sandbox.spy($, 'flashError');
|
this.flashErrorSpy = sandbox.spy($, 'flashError')
|
||||||
sandbox.stub(CurveGradesDialog.prototype, 'show');
|
sandbox.stub(CurveGradesDialog.prototype, 'show')
|
||||||
},
|
},
|
||||||
onSelect ({ isAdmin = false, inClosedGradingPeriod = false } = {}) {
|
onSelect({isAdmin = false, inClosedGradingPeriod = false} = {}) {
|
||||||
createCurveGradesAction({ inClosedGradingPeriod }, [], isAdmin, 'http://contextUrl/', true).onSelect()
|
createCurveGradesAction(
|
||||||
|
{inClosedGradingPeriod},
|
||||||
|
[],
|
||||||
|
isAdmin,
|
||||||
|
'http://contextUrl/',
|
||||||
|
true
|
||||||
|
).onSelect()
|
||||||
},
|
},
|
||||||
props ({ inClosedGradingPeriod = false, isAdmin = false } = {}) {
|
props({inClosedGradingPeriod = false, isAdmin = false} = {}) {
|
||||||
return [
|
return [
|
||||||
{ // assignment
|
{
|
||||||
|
// assignment
|
||||||
inClosedGradingPeriod
|
inClosedGradingPeriod
|
||||||
},
|
},
|
||||||
[], // students
|
[], // students
|
||||||
|
@ -85,56 +112,62 @@ define([
|
||||||
contextUrl: 'http://contextUrl/',
|
contextUrl: 'http://contextUrl/',
|
||||||
submissionsLoaded: true
|
submissionsLoaded: true
|
||||||
}
|
}
|
||||||
];
|
]
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
test('calls flashError if is not admin and in a closed grading period', function () {
|
test('calls flashError if is not admin and in a closed grading period', function() {
|
||||||
const props = this.props({ isAdmin: false, inClosedGradingPeriod: true });
|
const props = this.props({isAdmin: false, inClosedGradingPeriod: true})
|
||||||
createCurveGradesAction(...props).onSelect();
|
createCurveGradesAction(...props).onSelect()
|
||||||
ok(this.flashErrorSpy.withArgs(I18n.t('Unable to curve grades because this assignment is due in a closed ' +
|
ok(
|
||||||
'grading period for at least one student')).calledOnce);
|
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 () {
|
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 });
|
const props = this.props({isAdmin: false, inClosedGradingPeriod: true})
|
||||||
createCurveGradesAction(...props).onSelect();
|
createCurveGradesAction(...props).onSelect()
|
||||||
strictEqual(CurveGradesDialog.prototype.show.callCount, 0);
|
strictEqual(CurveGradesDialog.prototype.show.callCount, 0)
|
||||||
});
|
})
|
||||||
|
|
||||||
test('does not call flashError if is admin and in a closed grading period', function () {
|
test('does not call flashError if is admin and in a closed grading period', function() {
|
||||||
const props = this.props({ isAdmin: true, inClosedGradingPeriod: true });
|
const props = this.props({isAdmin: true, inClosedGradingPeriod: true})
|
||||||
createCurveGradesAction(...props).onSelect();
|
createCurveGradesAction(...props).onSelect()
|
||||||
ok(this.flashErrorSpy.notCalled);
|
ok(this.flashErrorSpy.notCalled)
|
||||||
});
|
})
|
||||||
|
|
||||||
test('calls curve grades dialog if is admin and in a closed grading period', function () {
|
test('calls curve grades dialog if is admin and in a closed grading period', function() {
|
||||||
const props = this.props({ isAdmin: true, inClosedGradingPeriod: true });
|
const props = this.props({isAdmin: true, inClosedGradingPeriod: true})
|
||||||
createCurveGradesAction(...props).onSelect();
|
createCurveGradesAction(...props).onSelect()
|
||||||
strictEqual(CurveGradesDialog.prototype.show.callCount, 1);
|
strictEqual(CurveGradesDialog.prototype.show.callCount, 1)
|
||||||
});
|
})
|
||||||
|
|
||||||
test('does not call flashError if is not admin and not in a closed grading period', function () {
|
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 });
|
const props = this.props({isAdmin: false, inClosedGradingPeriod: false})
|
||||||
createCurveGradesAction(...props).onSelect();
|
createCurveGradesAction(...props).onSelect()
|
||||||
ok(this.flashErrorSpy.notCalled);
|
ok(this.flashErrorSpy.notCalled)
|
||||||
});
|
})
|
||||||
|
|
||||||
test('calls curve grades dialog if is not admin and not in a closed grading period', function () {
|
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 });
|
const props = this.props({isAdmin: false, inClosedGradingPeriod: false})
|
||||||
createCurveGradesAction(...props).onSelect();
|
createCurveGradesAction(...props).onSelect()
|
||||||
strictEqual(CurveGradesDialog.prototype.show.callCount, 1);
|
strictEqual(CurveGradesDialog.prototype.show.callCount, 1)
|
||||||
});
|
})
|
||||||
|
|
||||||
test('does not call flashError if is admin and not in a closed grading period', function () {
|
test('does not call flashError if is admin and not in a closed grading period', function() {
|
||||||
const props = this.props({ isAdmin: true, inClosedGradingPeriod: false });
|
const props = this.props({isAdmin: true, inClosedGradingPeriod: false})
|
||||||
createCurveGradesAction(...props).onSelect();
|
createCurveGradesAction(...props).onSelect()
|
||||||
ok(this.flashErrorSpy.notCalled);
|
ok(this.flashErrorSpy.notCalled)
|
||||||
});
|
})
|
||||||
|
|
||||||
test('calls curve grades dialog if is admin and not in a closed grading period', function () {
|
test('calls curve grades dialog if is admin and not in a closed grading period', function() {
|
||||||
const props = this.props({ isAdmin: true, inClosedGradingPeriod: false });
|
const props = this.props({isAdmin: true, inClosedGradingPeriod: false})
|
||||||
createCurveGradesAction(...props).onSelect();
|
createCurveGradesAction(...props).onSelect()
|
||||||
strictEqual(CurveGradesDialog.prototype.show.callCount, 1);
|
strictEqual(CurveGradesDialog.prototype.show.callCount, 1)
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -16,8 +16,8 @@
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import $ from 'jquery';
|
import $ from 'jquery'
|
||||||
import fakeENV from 'helpers/fakeENV';
|
import fakeENV from 'helpers/fakeENV'
|
||||||
import DataLoader from 'jsx/gradezilla/DataLoader'
|
import DataLoader from 'jsx/gradezilla/DataLoader'
|
||||||
import {
|
import {
|
||||||
createGradebook,
|
createGradebook,
|
||||||
|
@ -25,158 +25,164 @@ import {
|
||||||
} from 'jsx/gradezilla/default_gradebook/__tests__/GradebookSpecHelper'
|
} from 'jsx/gradezilla/default_gradebook/__tests__/GradebookSpecHelper'
|
||||||
import SlickGridSpecHelper from '../../gradezilla/default_gradebook/GradebookGrid/GridSupport/SlickGridSpecHelper'
|
import SlickGridSpecHelper from '../../gradezilla/default_gradebook/GradebookGrid/GridSupport/SlickGridSpecHelper'
|
||||||
|
|
||||||
QUnit.module('Gradebook Grid Column Ordering', function (suiteHooks) {
|
QUnit.module('Gradebook Grid Column Ordering', function(suiteHooks) {
|
||||||
let $fixture;
|
let $fixture
|
||||||
let gridSpecHelper;
|
let gridSpecHelper
|
||||||
let gradebook;
|
let gradebook
|
||||||
let dataLoader;
|
let dataLoader
|
||||||
|
|
||||||
let assignmentGroups;
|
let assignmentGroups
|
||||||
let assignments;
|
let assignments
|
||||||
let contextModules;
|
let contextModules
|
||||||
let customColumns;
|
let customColumns
|
||||||
|
|
||||||
function createContextModules () {
|
function createContextModules() {
|
||||||
contextModules = [
|
contextModules = [
|
||||||
{ id: '2601', position: 3, name: 'Final Module' },
|
{id: '2601', position: 3, name: 'Final Module'},
|
||||||
{ id: '2602', position: 2, name: 'Second Module' },
|
{id: '2602', position: 2, name: 'Second Module'},
|
||||||
{ id: '2603', position: 1, name: 'First Module' }
|
{id: '2603', position: 1, name: 'First Module'}
|
||||||
];
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
function createCustomColumns () {
|
function createCustomColumns() {
|
||||||
customColumns = [
|
customColumns = [
|
||||||
{ id: '2401', teacher_notes: true, title: 'Notes' },
|
{id: '2401', teacher_notes: true, title: 'Notes'},
|
||||||
{ id: '2402', teacher_notes: false, title: 'Other Notes' }
|
{id: '2402', teacher_notes: false, title: 'Other Notes'}
|
||||||
];
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
function createAssignments () {
|
function createAssignments() {
|
||||||
assignments = {
|
assignments = {
|
||||||
homework: [{
|
homework: [
|
||||||
id: '2301',
|
{
|
||||||
assignment_group_id: '2201',
|
id: '2301',
|
||||||
course_id: '1201',
|
assignment_group_id: '2201',
|
||||||
due_at: '2015-05-04T12:00:00Z',
|
course_id: '1201',
|
||||||
html_url: '/assignments/2301',
|
due_at: '2015-05-04T12:00:00Z',
|
||||||
module_ids: ['2601'],
|
html_url: '/assignments/2301',
|
||||||
module_positions: [1],
|
module_ids: ['2601'],
|
||||||
muted: false,
|
module_positions: [1],
|
||||||
name: 'Math Assignment',
|
muted: false,
|
||||||
omit_from_final_grade: false,
|
name: 'Math Assignment',
|
||||||
points_possible: null,
|
omit_from_final_grade: false,
|
||||||
position: 1,
|
points_possible: null,
|
||||||
published: true,
|
position: 1,
|
||||||
submission_types: ['online_text_entry']
|
published: true,
|
||||||
}, {
|
submission_types: ['online_text_entry']
|
||||||
id: '2303',
|
},
|
||||||
assignment_group_id: '2201',
|
{
|
||||||
course_id: '1201',
|
id: '2303',
|
||||||
due_at: '2015-06-04T12:00:00Z',
|
assignment_group_id: '2201',
|
||||||
html_url: '/assignments/2302',
|
course_id: '1201',
|
||||||
module_ids: ['2601'],
|
due_at: '2015-06-04T12:00:00Z',
|
||||||
module_positions: [2],
|
html_url: '/assignments/2302',
|
||||||
muted: false,
|
module_ids: ['2601'],
|
||||||
name: 'English Assignment',
|
module_positions: [2],
|
||||||
omit_from_final_grade: false,
|
muted: false,
|
||||||
points_possible: 15,
|
name: 'English Assignment',
|
||||||
position: 2,
|
omit_from_final_grade: false,
|
||||||
published: true,
|
points_possible: 15,
|
||||||
submission_types: ['online_text_entry']
|
position: 2,
|
||||||
}],
|
published: true,
|
||||||
|
submission_types: ['online_text_entry']
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
quizzes: [{
|
quizzes: [
|
||||||
id: '2302',
|
{
|
||||||
assignment_group_id: '2202',
|
id: '2302',
|
||||||
course_id: '1201',
|
assignment_group_id: '2202',
|
||||||
due_at: '2015-05-05T12:00:00Z',
|
course_id: '1201',
|
||||||
html_url: '/assignments/2301',
|
due_at: '2015-05-05T12:00:00Z',
|
||||||
module_ids: ['2602'],
|
html_url: '/assignments/2301',
|
||||||
module_positions: [1],
|
module_ids: ['2602'],
|
||||||
muted: false,
|
module_positions: [1],
|
||||||
name: 'Math Quiz',
|
muted: false,
|
||||||
omit_from_final_grade: false,
|
name: 'Math Quiz',
|
||||||
points_possible: 10,
|
omit_from_final_grade: false,
|
||||||
position: 1,
|
points_possible: 10,
|
||||||
published: true,
|
position: 1,
|
||||||
submission_types: ['online_quiz']
|
published: true,
|
||||||
}, {
|
submission_types: ['online_quiz']
|
||||||
id: '2304',
|
},
|
||||||
assignment_group_id: '2202',
|
{
|
||||||
course_id: '1201',
|
id: '2304',
|
||||||
due_at: '2015-05-11T12:00:00Z',
|
assignment_group_id: '2202',
|
||||||
html_url: '/assignments/2302',
|
course_id: '1201',
|
||||||
module_ids: ['2603'],
|
due_at: '2015-05-11T12:00:00Z',
|
||||||
module_positions: [1],
|
html_url: '/assignments/2302',
|
||||||
muted: false,
|
module_ids: ['2603'],
|
||||||
name: 'English Quiz',
|
module_positions: [1],
|
||||||
omit_from_final_grade: false,
|
muted: false,
|
||||||
points_possible: 20,
|
name: 'English Quiz',
|
||||||
position: 2,
|
omit_from_final_grade: false,
|
||||||
published: true,
|
points_possible: 20,
|
||||||
submission_types: ['online_quiz']
|
position: 2,
|
||||||
}]
|
published: true,
|
||||||
};
|
submission_types: ['online_quiz']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createAssignmentGroups () {
|
function createAssignmentGroups() {
|
||||||
assignmentGroups = [
|
assignmentGroups = [
|
||||||
{ id: '2201', position: 2, name: 'Homework', assignments: assignments.homework },
|
{id: '2201', position: 2, name: 'Homework', assignments: assignments.homework},
|
||||||
{ id: '2202', position: 1, name: 'Quizzes', assignments: assignments.quizzes }
|
{id: '2202', position: 1, name: 'Quizzes', assignments: assignments.quizzes}
|
||||||
];
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
function addStudentIds () {
|
function addStudentIds() {
|
||||||
dataLoader.gotStudentIds.resolve({
|
dataLoader.gotStudentIds.resolve({
|
||||||
user_ids: ['1101']
|
user_ids: ['1101']
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function addGradingPeriodAssignments () {
|
function addGradingPeriodAssignments() {
|
||||||
dataLoader.gotGradingPeriodAssignments.resolve({
|
dataLoader.gotGradingPeriodAssignments.resolve({
|
||||||
grading_period_assignments: { 1401: ['2301'], 1402: ['2302'] }
|
grading_period_assignments: {1401: ['2301'], 1402: ['2302']}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function addContextModules () {
|
function addContextModules() {
|
||||||
dataLoader.gotContextModules.resolve(contextModules);
|
dataLoader.gotContextModules.resolve(contextModules)
|
||||||
}
|
}
|
||||||
|
|
||||||
function addCustomColumns () {
|
function addCustomColumns() {
|
||||||
dataLoader.gotCustomColumns.resolve(customColumns);
|
dataLoader.gotCustomColumns.resolve(customColumns)
|
||||||
}
|
}
|
||||||
|
|
||||||
function addAssignmentGroups () {
|
function addAssignmentGroups() {
|
||||||
dataLoader.gotAssignmentGroups.resolve(assignmentGroups);
|
dataLoader.gotAssignmentGroups.resolve(assignmentGroups)
|
||||||
}
|
}
|
||||||
|
|
||||||
function addGridData () {
|
function addGridData() {
|
||||||
addStudentIds();
|
addStudentIds()
|
||||||
addContextModules();
|
addContextModules()
|
||||||
addCustomColumns();
|
addCustomColumns()
|
||||||
addAssignmentGroups();
|
addAssignmentGroups()
|
||||||
addGradingPeriodAssignments();
|
addGradingPeriodAssignments()
|
||||||
}
|
}
|
||||||
|
|
||||||
function arrangeColumnsBy (sortType, direction) {
|
function arrangeColumnsBy(sortType, direction) {
|
||||||
gradebook.arrangeColumnsBy({ sortType, direction });
|
gradebook.arrangeColumnsBy({sortType, direction})
|
||||||
}
|
}
|
||||||
|
|
||||||
function createGradebookAndAddData (options) {
|
function createGradebookAndAddData(options) {
|
||||||
gradebook = createGradebook(options);
|
gradebook = createGradebook(options)
|
||||||
gradebook.initialize();
|
gradebook.initialize()
|
||||||
addGridData();
|
addGridData()
|
||||||
gridSpecHelper = new SlickGridSpecHelper(gradebook.gradebookGrid);
|
gridSpecHelper = new SlickGridSpecHelper(gradebook.gradebookGrid)
|
||||||
}
|
}
|
||||||
|
|
||||||
suiteHooks.beforeEach(function () {
|
suiteHooks.beforeEach(function() {
|
||||||
$fixture = document.createElement('div');
|
$fixture = document.createElement('div')
|
||||||
document.body.appendChild($fixture);
|
document.body.appendChild($fixture)
|
||||||
setFixtureHtml($fixture);
|
setFixtureHtml($fixture)
|
||||||
|
|
||||||
fakeENV.setup({
|
fakeENV.setup({
|
||||||
current_user_id: '1101'
|
current_user_id: '1101'
|
||||||
});
|
})
|
||||||
|
|
||||||
dataLoader = {
|
dataLoader = {
|
||||||
gotAssignmentGroups: $.Deferred(),
|
gotAssignmentGroups: $.Deferred(),
|
||||||
|
@ -187,272 +193,387 @@ QUnit.module('Gradebook Grid Column Ordering', function (suiteHooks) {
|
||||||
gotStudentIds: $.Deferred(),
|
gotStudentIds: $.Deferred(),
|
||||||
gotStudents: $.Deferred(),
|
gotStudents: $.Deferred(),
|
||||||
gotSubmissions: $.Deferred()
|
gotSubmissions: $.Deferred()
|
||||||
};
|
}
|
||||||
sinon.stub(DataLoader, 'loadGradebookData').returns(dataLoader);
|
sinon.stub(DataLoader, 'loadGradebookData').returns(dataLoader)
|
||||||
sinon.stub(DataLoader, 'getDataForColumn');
|
sinon.stub(DataLoader, 'getDataForColumn')
|
||||||
|
|
||||||
createAssignments();
|
createAssignments()
|
||||||
createAssignmentGroups();
|
createAssignmentGroups()
|
||||||
createContextModules();
|
createContextModules()
|
||||||
createCustomColumns();
|
createCustomColumns()
|
||||||
});
|
})
|
||||||
|
|
||||||
suiteHooks.afterEach(function () {
|
suiteHooks.afterEach(function() {
|
||||||
gradebook.destroy();
|
gradebook.destroy()
|
||||||
DataLoader.loadGradebookData.restore();
|
DataLoader.loadGradebookData.restore()
|
||||||
DataLoader.getDataForColumn.restore();
|
DataLoader.getDataForColumn.restore()
|
||||||
fakeENV.teardown();
|
fakeENV.teardown()
|
||||||
$fixture.remove();
|
$fixture.remove()
|
||||||
});
|
})
|
||||||
|
|
||||||
QUnit.module('when initializing the grid', function () {
|
QUnit.module('when initializing the grid', function() {
|
||||||
test('defaults assignment column order to assignment group positions when setting is not set', function () {
|
test('defaults assignment column order to assignment group positions when setting is not set', function() {
|
||||||
createGradebookAndAddData();
|
createGradebookAndAddData()
|
||||||
const expectedOrder = [
|
const expectedOrder = [
|
||||||
'assignment_2302', 'assignment_2304', 'assignment_2301', 'assignment_2303',
|
'assignment_2302',
|
||||||
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
|
'assignment_2304',
|
||||||
];
|
'assignment_2301',
|
||||||
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
|
'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 () {
|
test('sorts assignment columns by assignment name when setting is "name"', function() {
|
||||||
createGradebookAndAddData({
|
createGradebookAndAddData({
|
||||||
gradebook_column_order_settings: { sortType: 'name', direction: 'ascending' }
|
gradebook_column_order_settings: {sortType: 'name', direction: 'ascending'}
|
||||||
});
|
})
|
||||||
const expectedOrder = [
|
const expectedOrder = [
|
||||||
'assignment_2303', 'assignment_2304', 'assignment_2301', 'assignment_2302',
|
'assignment_2303',
|
||||||
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
|
'assignment_2304',
|
||||||
];
|
'assignment_2301',
|
||||||
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
|
'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 () {
|
test('sorts assignment columns by assignment due date when setting is "due date"', function() {
|
||||||
createGradebookAndAddData({
|
createGradebookAndAddData({
|
||||||
gradebook_column_order_settings: { sortType: 'due_date', direction: 'ascending' }
|
gradebook_column_order_settings: {sortType: 'due_date', direction: 'ascending'}
|
||||||
});
|
})
|
||||||
const expectedOrder = [
|
const expectedOrder = [
|
||||||
'assignment_2301', 'assignment_2302', 'assignment_2304', 'assignment_2303',
|
'assignment_2301',
|
||||||
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
|
'assignment_2302',
|
||||||
];
|
'assignment_2304',
|
||||||
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
|
'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 () {
|
test('sorts assignment columns by assignment points possible when setting is "points"', function() {
|
||||||
createGradebookAndAddData({
|
createGradebookAndAddData({
|
||||||
gradebook_column_order_settings: { sortType: 'points', direction: 'ascending' }
|
gradebook_column_order_settings: {sortType: 'points', direction: 'ascending'}
|
||||||
});
|
})
|
||||||
const expectedOrder = [
|
const expectedOrder = [
|
||||||
'assignment_2301', 'assignment_2302', 'assignment_2303', 'assignment_2304',
|
'assignment_2301',
|
||||||
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
|
'assignment_2302',
|
||||||
];
|
'assignment_2303',
|
||||||
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
|
'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 () {
|
test('sorts assignment columns by module position when setting is "module position"', function() {
|
||||||
createGradebookAndAddData({
|
createGradebookAndAddData({
|
||||||
gradebook_column_order_settings: { sortType: 'module_position', direction: 'ascending' }
|
gradebook_column_order_settings: {sortType: 'module_position', direction: 'ascending'}
|
||||||
});
|
})
|
||||||
const expectedOrder = [
|
const expectedOrder = [
|
||||||
'assignment_2304', 'assignment_2302', 'assignment_2301', 'assignment_2303',
|
'assignment_2304',
|
||||||
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
|
'assignment_2302',
|
||||||
];
|
'assignment_2301',
|
||||||
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
|
'assignment_2303',
|
||||||
});
|
'assignment_group_2202',
|
||||||
});
|
'assignment_group_2201',
|
||||||
|
'total_grade'
|
||||||
|
]
|
||||||
|
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
QUnit.module('when sorting by default', function () {
|
QUnit.module('when sorting by default', function() {
|
||||||
test('sorts assignment columns by assignment group position', function () {
|
test('sorts assignment columns by assignment group position', function() {
|
||||||
assignments.homework.splice(1, 1);
|
assignments.homework.splice(1, 1)
|
||||||
assignments.quizzes.splice(1, 1);
|
assignments.quizzes.splice(1, 1)
|
||||||
createGradebookAndAddData();
|
createGradebookAndAddData()
|
||||||
arrangeColumnsBy('default', 'ascending');
|
arrangeColumnsBy('default', 'ascending')
|
||||||
const expectedOrder = [
|
const expectedOrder = [
|
||||||
'assignment_2302', 'assignment_2301', 'assignment_group_2202', 'assignment_group_2201', 'total_grade'
|
'assignment_2302',
|
||||||
];
|
'assignment_2301',
|
||||||
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
|
'assignment_group_2202',
|
||||||
});
|
'assignment_group_2201',
|
||||||
|
'total_grade'
|
||||||
|
]
|
||||||
|
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
|
||||||
|
})
|
||||||
|
|
||||||
test('additionally sorts assignment columns by position within assignment groups', function () {
|
test('additionally sorts assignment columns by position within assignment groups', function() {
|
||||||
createGradebookAndAddData();
|
createGradebookAndAddData()
|
||||||
arrangeColumnsBy('default', 'ascending');
|
arrangeColumnsBy('default', 'ascending')
|
||||||
const expectedOrder = [
|
const expectedOrder = [
|
||||||
'assignment_2302', 'assignment_2304', 'assignment_2301', 'assignment_2303',
|
'assignment_2302',
|
||||||
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
|
'assignment_2304',
|
||||||
];
|
'assignment_2301',
|
||||||
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
|
'assignment_2303',
|
||||||
});
|
'assignment_group_2202',
|
||||||
|
'assignment_group_2201',
|
||||||
|
'total_grade'
|
||||||
|
]
|
||||||
|
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
|
||||||
|
})
|
||||||
|
|
||||||
test('optionally sorts in descending order', function () {
|
test('optionally sorts in descending order', function() {
|
||||||
createGradebookAndAddData();
|
createGradebookAndAddData()
|
||||||
arrangeColumnsBy('default', 'descending');
|
arrangeColumnsBy('default', 'descending')
|
||||||
const expectedOrder = [
|
const expectedOrder = [
|
||||||
'assignment_2303', 'assignment_2301', 'assignment_2304', 'assignment_2302',
|
'assignment_2303',
|
||||||
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
|
'assignment_2301',
|
||||||
];
|
'assignment_2304',
|
||||||
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
|
'assignment_2302',
|
||||||
});
|
'assignment_group_2202',
|
||||||
});
|
'assignment_group_2201',
|
||||||
|
'total_grade'
|
||||||
|
]
|
||||||
|
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
QUnit.module('when sorting by name', function () {
|
QUnit.module('when sorting by name', function() {
|
||||||
test('sorts assignment columns by assignment name', function () {
|
test('sorts assignment columns by assignment name', function() {
|
||||||
createGradebookAndAddData();
|
createGradebookAndAddData()
|
||||||
arrangeColumnsBy('name', 'ascending');
|
arrangeColumnsBy('name', 'ascending')
|
||||||
const expectedOrder = [
|
const expectedOrder = [
|
||||||
'assignment_2303', 'assignment_2304', 'assignment_2301', 'assignment_2302',
|
'assignment_2303',
|
||||||
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
|
'assignment_2304',
|
||||||
];
|
'assignment_2301',
|
||||||
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
|
'assignment_2302',
|
||||||
});
|
'assignment_group_2202',
|
||||||
|
'assignment_group_2201',
|
||||||
|
'total_grade'
|
||||||
|
]
|
||||||
|
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
|
||||||
|
})
|
||||||
|
|
||||||
test('optionally sorts in descending order', function () {
|
test('optionally sorts in descending order', function() {
|
||||||
createGradebookAndAddData();
|
createGradebookAndAddData()
|
||||||
arrangeColumnsBy('name', 'descending');
|
arrangeColumnsBy('name', 'descending')
|
||||||
const expectedOrder = [
|
const expectedOrder = [
|
||||||
'assignment_2302', 'assignment_2301', 'assignment_2304', 'assignment_2303',
|
'assignment_2302',
|
||||||
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
|
'assignment_2301',
|
||||||
];
|
'assignment_2304',
|
||||||
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
|
'assignment_2303',
|
||||||
});
|
'assignment_group_2202',
|
||||||
});
|
'assignment_group_2201',
|
||||||
|
'total_grade'
|
||||||
|
]
|
||||||
|
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
QUnit.module('when sorting by due date', function () {
|
QUnit.module('when sorting by due date', function() {
|
||||||
test('sorts assignment columns by assignment due date', function () {
|
test('sorts assignment columns by assignment due date', function() {
|
||||||
createGradebookAndAddData();
|
createGradebookAndAddData()
|
||||||
arrangeColumnsBy('due_date', 'ascending');
|
arrangeColumnsBy('due_date', 'ascending')
|
||||||
const expectedOrder = [
|
const expectedOrder = [
|
||||||
'assignment_2301', 'assignment_2302', 'assignment_2304', 'assignment_2303',
|
'assignment_2301',
|
||||||
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
|
'assignment_2302',
|
||||||
];
|
'assignment_2304',
|
||||||
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
|
'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 () {
|
test('sorts assignments with due dates before assignments without due dates', function() {
|
||||||
assignments.quizzes[0].due_at = null;
|
assignments.quizzes[0].due_at = null
|
||||||
createGradebookAndAddData();
|
createGradebookAndAddData()
|
||||||
arrangeColumnsBy('due_date', 'ascending');
|
arrangeColumnsBy('due_date', 'ascending')
|
||||||
const expectedOrder = [
|
const expectedOrder = [
|
||||||
'assignment_2301', 'assignment_2304', 'assignment_2303', 'assignment_2302',
|
'assignment_2301',
|
||||||
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
|
'assignment_2304',
|
||||||
];
|
'assignment_2303',
|
||||||
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
|
'assignment_2302',
|
||||||
});
|
'assignment_group_2202',
|
||||||
|
'assignment_group_2201',
|
||||||
|
'total_grade'
|
||||||
|
]
|
||||||
|
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
|
||||||
|
})
|
||||||
|
|
||||||
test('optionally sorts in descending order', function () {
|
test('optionally sorts in descending order', function() {
|
||||||
createGradebookAndAddData();
|
createGradebookAndAddData()
|
||||||
arrangeColumnsBy('due_date', 'descending');
|
arrangeColumnsBy('due_date', 'descending')
|
||||||
const expectedOrder = [
|
const expectedOrder = [
|
||||||
'assignment_2303', 'assignment_2304', 'assignment_2302', 'assignment_2301',
|
'assignment_2303',
|
||||||
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
|
'assignment_2304',
|
||||||
];
|
'assignment_2302',
|
||||||
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
|
'assignment_2301',
|
||||||
});
|
'assignment_group_2202',
|
||||||
});
|
'assignment_group_2201',
|
||||||
|
'total_grade'
|
||||||
|
]
|
||||||
|
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
QUnit.module('when sorting by points', function () {
|
QUnit.module('when sorting by points', function() {
|
||||||
test('sorts assignment columns by assignment points possible', function () {
|
test('sorts assignment columns by assignment points possible', function() {
|
||||||
createGradebookAndAddData();
|
createGradebookAndAddData()
|
||||||
arrangeColumnsBy('points', 'ascending');
|
arrangeColumnsBy('points', 'ascending')
|
||||||
const expectedOrder = [
|
const expectedOrder = [
|
||||||
'assignment_2301', 'assignment_2302', 'assignment_2303', 'assignment_2304',
|
'assignment_2301',
|
||||||
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
|
'assignment_2302',
|
||||||
];
|
'assignment_2303',
|
||||||
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
|
'assignment_2304',
|
||||||
});
|
'assignment_group_2202',
|
||||||
|
'assignment_group_2201',
|
||||||
|
'total_grade'
|
||||||
|
]
|
||||||
|
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
|
||||||
|
})
|
||||||
|
|
||||||
test('optionally sorts in descending order', function () {
|
test('optionally sorts in descending order', function() {
|
||||||
createGradebookAndAddData();
|
createGradebookAndAddData()
|
||||||
arrangeColumnsBy('points', 'descending');
|
arrangeColumnsBy('points', 'descending')
|
||||||
const expectedOrder = [
|
const expectedOrder = [
|
||||||
'assignment_2304', 'assignment_2303', 'assignment_2302', 'assignment_2301',
|
'assignment_2304',
|
||||||
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
|
'assignment_2303',
|
||||||
];
|
'assignment_2302',
|
||||||
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
|
'assignment_2301',
|
||||||
});
|
'assignment_group_2202',
|
||||||
});
|
'assignment_group_2201',
|
||||||
|
'total_grade'
|
||||||
|
]
|
||||||
|
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
QUnit.module('when sorting by module position', function () {
|
QUnit.module('when sorting by module position', function() {
|
||||||
test('sorts assignment columns by module position', function () {
|
test('sorts assignment columns by module position', function() {
|
||||||
assignments.homework.splice(1, 1);
|
assignments.homework.splice(1, 1)
|
||||||
createGradebookAndAddData();
|
createGradebookAndAddData()
|
||||||
arrangeColumnsBy('module_position', 'ascending');
|
arrangeColumnsBy('module_position', 'ascending')
|
||||||
const expectedOrder = [
|
const expectedOrder = [
|
||||||
'assignment_2304', 'assignment_2302', 'assignment_2301',
|
'assignment_2304',
|
||||||
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
|
'assignment_2302',
|
||||||
];
|
'assignment_2301',
|
||||||
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
|
'assignment_group_2202',
|
||||||
});
|
'assignment_group_2201',
|
||||||
|
'total_grade'
|
||||||
|
]
|
||||||
|
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
|
||||||
|
})
|
||||||
|
|
||||||
test('additionally sorts assignment columns by position within modules', function () {
|
test('additionally sorts assignment columns by position within modules', function() {
|
||||||
createGradebookAndAddData();
|
createGradebookAndAddData()
|
||||||
arrangeColumnsBy('module_position', 'ascending');
|
arrangeColumnsBy('module_position', 'ascending')
|
||||||
const expectedOrder = [
|
const expectedOrder = [
|
||||||
'assignment_2304', 'assignment_2302', 'assignment_2301', 'assignment_2303',
|
'assignment_2304',
|
||||||
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
|
'assignment_2302',
|
||||||
];
|
'assignment_2301',
|
||||||
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
|
'assignment_2303',
|
||||||
});
|
'assignment_group_2202',
|
||||||
|
'assignment_group_2201',
|
||||||
|
'total_grade'
|
||||||
|
]
|
||||||
|
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
|
||||||
|
})
|
||||||
|
|
||||||
test('sorts assignments with modules before assignments without modules', function () {
|
test('sorts assignments with modules before assignments without modules', function() {
|
||||||
assignments.quizzes[0].module_ids = [];
|
assignments.quizzes[0].module_ids = []
|
||||||
assignments.quizzes[0].module_positions = [];
|
assignments.quizzes[0].module_positions = []
|
||||||
createGradebookAndAddData();
|
createGradebookAndAddData()
|
||||||
arrangeColumnsBy('module_position', 'ascending');
|
arrangeColumnsBy('module_position', 'ascending')
|
||||||
const expectedOrder = [
|
const expectedOrder = [
|
||||||
'assignment_2304', 'assignment_2301', 'assignment_2303', 'assignment_2302',
|
'assignment_2304',
|
||||||
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
|
'assignment_2301',
|
||||||
];
|
'assignment_2303',
|
||||||
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
|
'assignment_2302',
|
||||||
});
|
'assignment_group_2202',
|
||||||
|
'assignment_group_2201',
|
||||||
|
'total_grade'
|
||||||
|
]
|
||||||
|
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
|
||||||
|
})
|
||||||
|
|
||||||
test('optionally sorts in descending order', function () {
|
test('optionally sorts in descending order', function() {
|
||||||
createGradebookAndAddData();
|
createGradebookAndAddData()
|
||||||
arrangeColumnsBy('module_position', 'descending');
|
arrangeColumnsBy('module_position', 'descending')
|
||||||
const expectedOrder = [
|
const expectedOrder = [
|
||||||
'assignment_2303', 'assignment_2301', 'assignment_2302', 'assignment_2304',
|
'assignment_2303',
|
||||||
'assignment_group_2202', 'assignment_group_2201', 'total_grade'
|
'assignment_2301',
|
||||||
];
|
'assignment_2302',
|
||||||
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
|
'assignment_2304',
|
||||||
});
|
'assignment_group_2202',
|
||||||
});
|
'assignment_group_2201',
|
||||||
|
'total_grade'
|
||||||
|
]
|
||||||
|
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
QUnit.module('when using a custom order', function () {
|
QUnit.module('when using a custom order', function() {
|
||||||
test('sorts all saved columns in the saved order', function () {
|
test('sorts all saved columns in the saved order', function() {
|
||||||
const customOrder = [
|
const customOrder = [
|
||||||
'total_grade', 'assignment_group_2201', 'assignment_2301', 'assignment_2303',
|
'total_grade',
|
||||||
'assignment_group_2202', 'assignment_2302', 'assignment_2304'
|
'assignment_group_2201',
|
||||||
];
|
'assignment_2301',
|
||||||
|
'assignment_2303',
|
||||||
|
'assignment_group_2202',
|
||||||
|
'assignment_2302',
|
||||||
|
'assignment_2304'
|
||||||
|
]
|
||||||
createGradebookAndAddData({
|
createGradebookAndAddData({
|
||||||
gradebook_column_order_settings: { sortType: 'custom', customOrder }
|
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 () {
|
test('sorts any unsaved columns after the saved order', function() {
|
||||||
const customOrder = [
|
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({
|
createGradebookAndAddData({
|
||||||
gradebook_column_order_settings: { sortType: 'custom', customOrder }
|
gradebook_column_order_settings: {sortType: 'custom', customOrder}
|
||||||
});
|
})
|
||||||
const expectedOrder = [
|
const expectedOrder = [
|
||||||
'total_grade', 'assignment_2301', 'assignment_group_2202', 'assignment_2302',
|
'total_grade',
|
||||||
'assignment_2304', 'assignment_2303', 'assignment_group_2201'
|
'assignment_2301',
|
||||||
];
|
'assignment_group_2202',
|
||||||
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
|
'assignment_2302',
|
||||||
});
|
'assignment_2304',
|
||||||
|
'assignment_2303',
|
||||||
|
'assignment_group_2201'
|
||||||
|
]
|
||||||
|
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
|
||||||
|
})
|
||||||
|
|
||||||
test('sorts unsaved columns by assignment group position', function () {
|
test('sorts unsaved columns by assignment group position', function() {
|
||||||
const customOrder = [
|
const customOrder = [
|
||||||
'total_grade', 'assignment_2301', 'assignment_group_2202', 'assignment_group_2201'
|
'total_grade',
|
||||||
];
|
'assignment_2301',
|
||||||
|
'assignment_group_2202',
|
||||||
|
'assignment_group_2201'
|
||||||
|
]
|
||||||
createGradebookAndAddData({
|
createGradebookAndAddData({
|
||||||
gradebook_column_order_settings: { sortType: 'custom', customOrder }
|
gradebook_column_order_settings: {sortType: 'custom', customOrder}
|
||||||
});
|
})
|
||||||
const expectedOrder = [
|
const expectedOrder = [
|
||||||
'total_grade', 'assignment_2301', 'assignment_group_2202', 'assignment_group_2201',
|
'total_grade',
|
||||||
'assignment_2302', 'assignment_2304', 'assignment_2303'
|
'assignment_2301',
|
||||||
];
|
'assignment_group_2202',
|
||||||
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder);
|
'assignment_group_2201',
|
||||||
});
|
'assignment_2302',
|
||||||
});
|
'assignment_2304',
|
||||||
});
|
'assignment_2303'
|
||||||
|
]
|
||||||
|
deepEqual(gridSpecHelper.listScrollableColumnIds(), expectedOrder)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
|
@ -16,8 +16,8 @@
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import $ from 'jquery';
|
import $ from 'jquery'
|
||||||
import fakeENV from 'helpers/fakeENV';
|
import fakeENV from 'helpers/fakeENV'
|
||||||
import DataLoader from 'jsx/gradezilla/DataLoader'
|
import DataLoader from 'jsx/gradezilla/DataLoader'
|
||||||
import {
|
import {
|
||||||
createGradebook,
|
createGradebook,
|
||||||
|
@ -25,154 +25,160 @@ import {
|
||||||
} from 'jsx/gradezilla/default_gradebook/__tests__/GradebookSpecHelper'
|
} from 'jsx/gradezilla/default_gradebook/__tests__/GradebookSpecHelper'
|
||||||
import SlickGridSpecHelper from '../../gradezilla/default_gradebook/GradebookGrid/GridSupport/SlickGridSpecHelper'
|
import SlickGridSpecHelper from '../../gradezilla/default_gradebook/GradebookGrid/GridSupport/SlickGridSpecHelper'
|
||||||
|
|
||||||
QUnit.module('Gradebook Grid Column Widths', (suiteHooks) => {
|
QUnit.module('Gradebook Grid Column Widths', suiteHooks => {
|
||||||
let $fixture;
|
let $fixture
|
||||||
let gridSpecHelper;
|
let gridSpecHelper
|
||||||
let gradebook;
|
let gradebook
|
||||||
let dataLoader;
|
let dataLoader
|
||||||
|
|
||||||
let assignmentGroups;
|
let assignmentGroups
|
||||||
let assignments;
|
let assignments
|
||||||
let contextModules;
|
let contextModules
|
||||||
let customColumns;
|
let customColumns
|
||||||
|
|
||||||
function createContextModules () {
|
function createContextModules() {
|
||||||
contextModules = [
|
contextModules = [
|
||||||
{ id: '2601', position: 3, name: 'Final Module' },
|
{id: '2601', position: 3, name: 'Final Module'},
|
||||||
{ id: '2602', position: 2, name: 'Second Module' },
|
{id: '2602', position: 2, name: 'Second Module'},
|
||||||
{ id: '2603', position: 1, name: 'First Module' }
|
{id: '2603', position: 1, name: 'First Module'}
|
||||||
];
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
function createCustomColumns () {
|
function createCustomColumns() {
|
||||||
customColumns = [
|
customColumns = [
|
||||||
{ id: '2401', teacher_notes: true, title: 'Notes' },
|
{id: '2401', teacher_notes: true, title: 'Notes'},
|
||||||
{ id: '2402', teacher_notes: false, title: 'Other Notes' }
|
{id: '2402', teacher_notes: false, title: 'Other Notes'}
|
||||||
];
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
function createAssignments () {
|
function createAssignments() {
|
||||||
assignments = {
|
assignments = {
|
||||||
homework: [{
|
homework: [
|
||||||
id: '2301',
|
{
|
||||||
assignment_group_id: '2201',
|
id: '2301',
|
||||||
course_id: '1201',
|
assignment_group_id: '2201',
|
||||||
due_at: '2015-05-04T12:00:00Z',
|
course_id: '1201',
|
||||||
html_url: '/assignments/2301',
|
due_at: '2015-05-04T12:00:00Z',
|
||||||
module_ids: ['2601'],
|
html_url: '/assignments/2301',
|
||||||
module_positions: [1],
|
module_ids: ['2601'],
|
||||||
muted: false,
|
module_positions: [1],
|
||||||
name: 'Math Assignment',
|
muted: false,
|
||||||
omit_from_final_grade: false,
|
name: 'Math Assignment',
|
||||||
points_possible: null,
|
omit_from_final_grade: false,
|
||||||
position: 1,
|
points_possible: null,
|
||||||
published: true,
|
position: 1,
|
||||||
submission_types: ['online_text_entry']
|
published: true,
|
||||||
}, {
|
submission_types: ['online_text_entry']
|
||||||
id: '2303',
|
},
|
||||||
assignment_group_id: '2201',
|
{
|
||||||
course_id: '1201',
|
id: '2303',
|
||||||
due_at: '2015-06-04T12:00:00Z',
|
assignment_group_id: '2201',
|
||||||
html_url: '/assignments/2303',
|
course_id: '1201',
|
||||||
module_ids: ['2601'],
|
due_at: '2015-06-04T12:00:00Z',
|
||||||
module_positions: [2],
|
html_url: '/assignments/2303',
|
||||||
muted: false,
|
module_ids: ['2601'],
|
||||||
name: 'English Assignment',
|
module_positions: [2],
|
||||||
omit_from_final_grade: false,
|
muted: false,
|
||||||
points_possible: 15,
|
name: 'English Assignment',
|
||||||
position: 2,
|
omit_from_final_grade: false,
|
||||||
published: true,
|
points_possible: 15,
|
||||||
submission_types: ['online_text_entry']
|
position: 2,
|
||||||
}],
|
published: true,
|
||||||
|
submission_types: ['online_text_entry']
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
quizzes: [{
|
quizzes: [
|
||||||
id: '2302',
|
{
|
||||||
assignment_group_id: '2202',
|
id: '2302',
|
||||||
course_id: '1201',
|
assignment_group_id: '2202',
|
||||||
due_at: '2015-05-05T12:00:00Z',
|
course_id: '1201',
|
||||||
html_url: '/assignments/2302',
|
due_at: '2015-05-05T12:00:00Z',
|
||||||
module_ids: ['2602'],
|
html_url: '/assignments/2302',
|
||||||
module_positions: [1],
|
module_ids: ['2602'],
|
||||||
muted: false,
|
module_positions: [1],
|
||||||
name: 'Math Quiz',
|
muted: false,
|
||||||
omit_from_final_grade: false,
|
name: 'Math Quiz',
|
||||||
points_possible: 10,
|
omit_from_final_grade: false,
|
||||||
position: 1,
|
points_possible: 10,
|
||||||
published: true,
|
position: 1,
|
||||||
submission_types: ['online_quiz']
|
published: true,
|
||||||
}, {
|
submission_types: ['online_quiz']
|
||||||
id: '2304',
|
},
|
||||||
assignment_group_id: '2202',
|
{
|
||||||
course_id: '1201',
|
id: '2304',
|
||||||
due_at: '2015-05-11T12:00:00Z',
|
assignment_group_id: '2202',
|
||||||
html_url: '/assignments/2304',
|
course_id: '1201',
|
||||||
module_ids: ['2603'],
|
due_at: '2015-05-11T12:00:00Z',
|
||||||
module_positions: [1],
|
html_url: '/assignments/2304',
|
||||||
muted: false,
|
module_ids: ['2603'],
|
||||||
name: 'English Quiz',
|
module_positions: [1],
|
||||||
omit_from_final_grade: false,
|
muted: false,
|
||||||
points_possible: 20,
|
name: 'English Quiz',
|
||||||
position: 2,
|
omit_from_final_grade: false,
|
||||||
published: true,
|
points_possible: 20,
|
||||||
submission_types: ['online_quiz']
|
position: 2,
|
||||||
}]
|
published: true,
|
||||||
};
|
submission_types: ['online_quiz']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createAssignmentGroups () {
|
function createAssignmentGroups() {
|
||||||
assignmentGroups = [
|
assignmentGroups = [
|
||||||
{ id: '2201', position: 2, name: 'Homework', assignments: assignments.homework },
|
{id: '2201', position: 2, name: 'Homework', assignments: assignments.homework},
|
||||||
{ id: '2202', position: 1, name: 'Quizzes', assignments: assignments.quizzes }
|
{id: '2202', position: 1, name: 'Quizzes', assignments: assignments.quizzes}
|
||||||
];
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
function addStudentIds () {
|
function addStudentIds() {
|
||||||
dataLoader.gotStudentIds.resolve({
|
dataLoader.gotStudentIds.resolve({
|
||||||
user_ids: ['1101']
|
user_ids: ['1101']
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function addGradingPeriodAssignments () {
|
function addGradingPeriodAssignments() {
|
||||||
dataLoader.gotGradingPeriodAssignments.resolve({
|
dataLoader.gotGradingPeriodAssignments.resolve({
|
||||||
grading_period_assignments: { 1401: ['2301'], 1402: ['2302'] }
|
grading_period_assignments: {1401: ['2301'], 1402: ['2302']}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function addContextModules () {
|
function addContextModules() {
|
||||||
dataLoader.gotContextModules.resolve(contextModules);
|
dataLoader.gotContextModules.resolve(contextModules)
|
||||||
}
|
}
|
||||||
|
|
||||||
function addCustomColumns () {
|
function addCustomColumns() {
|
||||||
dataLoader.gotCustomColumns.resolve(customColumns);
|
dataLoader.gotCustomColumns.resolve(customColumns)
|
||||||
}
|
}
|
||||||
|
|
||||||
function addAssignmentGroups () {
|
function addAssignmentGroups() {
|
||||||
dataLoader.gotAssignmentGroups.resolve(assignmentGroups);
|
dataLoader.gotAssignmentGroups.resolve(assignmentGroups)
|
||||||
}
|
}
|
||||||
|
|
||||||
function addGridData () {
|
function addGridData() {
|
||||||
addStudentIds();
|
addStudentIds()
|
||||||
addContextModules();
|
addContextModules()
|
||||||
addCustomColumns();
|
addCustomColumns()
|
||||||
addAssignmentGroups();
|
addAssignmentGroups()
|
||||||
addGradingPeriodAssignments();
|
addGradingPeriodAssignments()
|
||||||
}
|
}
|
||||||
|
|
||||||
function createGradebookAndAddData (options) {
|
function createGradebookAndAddData(options) {
|
||||||
gradebook = createGradebook(options);
|
gradebook = createGradebook(options)
|
||||||
gradebook.initialize();
|
gradebook.initialize()
|
||||||
addGridData();
|
addGridData()
|
||||||
gridSpecHelper = new SlickGridSpecHelper(gradebook.gradebookGrid);
|
gridSpecHelper = new SlickGridSpecHelper(gradebook.gradebookGrid)
|
||||||
}
|
}
|
||||||
|
|
||||||
suiteHooks.beforeEach(() => {
|
suiteHooks.beforeEach(() => {
|
||||||
$fixture = document.createElement('div');
|
$fixture = document.createElement('div')
|
||||||
document.body.appendChild($fixture);
|
document.body.appendChild($fixture)
|
||||||
setFixtureHtml($fixture);
|
setFixtureHtml($fixture)
|
||||||
|
|
||||||
fakeENV.setup({
|
fakeENV.setup({
|
||||||
current_user_id: '1101'
|
current_user_id: '1101'
|
||||||
});
|
})
|
||||||
|
|
||||||
dataLoader = {
|
dataLoader = {
|
||||||
gotAssignmentGroups: $.Deferred(),
|
gotAssignmentGroups: $.Deferred(),
|
||||||
|
@ -183,100 +189,103 @@ QUnit.module('Gradebook Grid Column Widths', (suiteHooks) => {
|
||||||
gotStudentIds: $.Deferred(),
|
gotStudentIds: $.Deferred(),
|
||||||
gotStudents: $.Deferred(),
|
gotStudents: $.Deferred(),
|
||||||
gotSubmissions: $.Deferred()
|
gotSubmissions: $.Deferred()
|
||||||
};
|
}
|
||||||
sinon.stub(DataLoader, 'loadGradebookData').returns(dataLoader);
|
sinon.stub(DataLoader, 'loadGradebookData').returns(dataLoader)
|
||||||
sinon.stub(DataLoader, 'getDataForColumn');
|
sinon.stub(DataLoader, 'getDataForColumn')
|
||||||
|
|
||||||
createAssignments();
|
createAssignments()
|
||||||
createAssignmentGroups();
|
createAssignmentGroups()
|
||||||
createContextModules();
|
createContextModules()
|
||||||
createCustomColumns();
|
createCustomColumns()
|
||||||
});
|
})
|
||||||
|
|
||||||
suiteHooks.afterEach(() => {
|
suiteHooks.afterEach(() => {
|
||||||
gradebook.gradebookGrid.destroy();
|
gradebook.gradebookGrid.destroy()
|
||||||
$(document).unbind('gridready');
|
$(document).unbind('gridready')
|
||||||
DataLoader.loadGradebookData.restore();
|
DataLoader.loadGradebookData.restore()
|
||||||
DataLoader.getDataForColumn.restore();
|
DataLoader.getDataForColumn.restore()
|
||||||
fakeENV.teardown();
|
fakeENV.teardown()
|
||||||
$fixture.remove();
|
$fixture.remove()
|
||||||
});
|
})
|
||||||
|
|
||||||
QUnit.module('when initializing the grid', (hooks) => {
|
QUnit.module('when initializing the grid', hooks => {
|
||||||
hooks.beforeEach(() => {
|
hooks.beforeEach(() => {
|
||||||
gradebook = createGradebook();
|
gradebook = createGradebook()
|
||||||
gradebook.gradebookColumnSizeSettings = { assignment_2302: 10, assignment_2303: 54 };
|
gradebook.gradebookColumnSizeSettings = {assignment_2302: 10, assignment_2303: 54}
|
||||||
gradebook.initialize();
|
gradebook.initialize()
|
||||||
addGridData();
|
addGridData()
|
||||||
gridSpecHelper = new SlickGridSpecHelper(gradebook.gradebookGrid);
|
gridSpecHelper = new SlickGridSpecHelper(gradebook.gradebookGrid)
|
||||||
});
|
})
|
||||||
|
|
||||||
test('defaults assignment column size to fit the assignment name', () => {
|
test('defaults assignment column size to fit the assignment name', () => {
|
||||||
const columnNode = gridSpecHelper.getColumnHeaderNode('assignment_2301');
|
const columnNode = gridSpecHelper.getColumnHeaderNode('assignment_2301')
|
||||||
ok(columnNode.offsetWidth > 10, 'width is not the minimum');
|
ok(columnNode.offsetWidth > 10, 'width is not the minimum')
|
||||||
});
|
})
|
||||||
|
|
||||||
test('uses a stored width for assignment column headers', () => {
|
test('uses a stored width for assignment column headers', () => {
|
||||||
const columnNode = gridSpecHelper.getColumnHeaderNode('assignment_2303');
|
const columnNode = gridSpecHelper.getColumnHeaderNode('assignment_2303')
|
||||||
strictEqual(columnNode.offsetWidth, 54);
|
strictEqual(columnNode.offsetWidth, 54)
|
||||||
});
|
})
|
||||||
|
|
||||||
test('hides assignment column header content when the column is minimized', () => {
|
test('hides assignment column header content when the column is minimized', () => {
|
||||||
const columnNode = gridSpecHelper.getColumnHeaderNode('assignment_2302');
|
const columnNode = gridSpecHelper.getColumnHeaderNode('assignment_2302')
|
||||||
ok(columnNode.classList.contains('minimized'));
|
ok(columnNode.classList.contains('minimized'))
|
||||||
});
|
})
|
||||||
|
|
||||||
test('hides assignment column cell content when the column is minimized', () => {
|
test('hides assignment column cell content when the column is minimized', () => {
|
||||||
const columnIndex = gridSpecHelper.listColumnIds().indexOf('assignment_2302');
|
const columnIndex = gridSpecHelper.listColumnIds().indexOf('assignment_2302')
|
||||||
const cellNode = gradebook.gradebookGrid.grid.getCellNode(0, columnIndex);
|
const cellNode = gradebook.gradebookGrid.grid.getCellNode(0, columnIndex)
|
||||||
ok(cellNode.classList.contains('minimized'));
|
ok(cellNode.classList.contains('minimized'))
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
||||||
QUnit.module('onColumnsResized', (hooks) => {
|
QUnit.module('onColumnsResized', hooks => {
|
||||||
function resizeColumn (columnId, widthChange) {
|
function resizeColumn(columnId, widthChange) {
|
||||||
const column = gridSpecHelper.getColumn(columnId);
|
const column = gridSpecHelper.getColumn(columnId)
|
||||||
const updatedColumn = { ...column, width: column.width + widthChange };
|
const updatedColumn = {...column, width: column.width + widthChange}
|
||||||
gradebook.gradebookGrid.gridSupport.events.onColumnsResized.trigger(null, [updatedColumn]);
|
gradebook.gradebookGrid.gridSupport.events.onColumnsResized.trigger(null, [updatedColumn])
|
||||||
}
|
}
|
||||||
|
|
||||||
hooks.beforeEach(() => {
|
hooks.beforeEach(() => {
|
||||||
createGradebookAndAddData();
|
createGradebookAndAddData()
|
||||||
sinon.stub(gradebook, 'saveColumnWidthPreference');
|
sinon.stub(gradebook, 'saveColumnWidthPreference')
|
||||||
});
|
})
|
||||||
|
|
||||||
test('updates the column definitions for resized columns', () => {
|
test('updates the column definitions for resized columns', () => {
|
||||||
const originalWidth = gridSpecHelper.getColumn('assignment_2304').width;
|
const originalWidth = gridSpecHelper.getColumn('assignment_2304').width
|
||||||
resizeColumn('assignment_2304', -20);
|
resizeColumn('assignment_2304', -20)
|
||||||
strictEqual(gradebook.gradebookGrid.gridData.columns.definitions.assignment_2304.width, originalWidth - 20);
|
strictEqual(
|
||||||
});
|
gradebook.gradebookGrid.gridData.columns.definitions.assignment_2304.width,
|
||||||
|
originalWidth - 20
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
test('hides assignment column header content when the column is minimized', () => {
|
test('hides assignment column header content when the column is minimized', () => {
|
||||||
resizeColumn('assignment_2304', -100);
|
resizeColumn('assignment_2304', -100)
|
||||||
const columnNode = gridSpecHelper.getColumnHeaderNode('assignment_2304');
|
const columnNode = gridSpecHelper.getColumnHeaderNode('assignment_2304')
|
||||||
ok(columnNode.classList.contains('minimized'));
|
ok(columnNode.classList.contains('minimized'))
|
||||||
});
|
})
|
||||||
|
|
||||||
test('hides assignment column cell content when the column is minimized', () => {
|
test('hides assignment column cell content when the column is minimized', () => {
|
||||||
resizeColumn('assignment_2304', -100);
|
resizeColumn('assignment_2304', -100)
|
||||||
const columnIndex = gridSpecHelper.listColumnIds().indexOf('assignment_2304');
|
const columnIndex = gridSpecHelper.listColumnIds().indexOf('assignment_2304')
|
||||||
const cellNode = gradebook.gradebookGrid.grid.getCellNode(0, columnIndex);
|
const cellNode = gradebook.gradebookGrid.grid.getCellNode(0, columnIndex)
|
||||||
ok(cellNode.classList.contains('minimized'));
|
ok(cellNode.classList.contains('minimized'))
|
||||||
});
|
})
|
||||||
|
|
||||||
test('unhides assignment column header content when the column is unminimized', () => {
|
test('unhides assignment column header content when the column is unminimized', () => {
|
||||||
resizeColumn('assignment_2304', -100);
|
resizeColumn('assignment_2304', -100)
|
||||||
resizeColumn('assignment_2304', 1);
|
resizeColumn('assignment_2304', 1)
|
||||||
const columnNode = gridSpecHelper.getColumnHeaderNode('assignment_2304');
|
const columnNode = gridSpecHelper.getColumnHeaderNode('assignment_2304')
|
||||||
notOk(columnNode.classList.contains('minimized'));
|
notOk(columnNode.classList.contains('minimized'))
|
||||||
});
|
})
|
||||||
|
|
||||||
test('unhides assignment column cell content when the column is unminimized', () => {
|
test('unhides assignment column cell content when the column is unminimized', () => {
|
||||||
resizeColumn('assignment_2304', -100);
|
resizeColumn('assignment_2304', -100)
|
||||||
resizeColumn('assignment_2304', 1);
|
resizeColumn('assignment_2304', 1)
|
||||||
const columnIndex = gridSpecHelper.listColumnIds().indexOf('assignment_2304');
|
const columnIndex = gridSpecHelper.listColumnIds().indexOf('assignment_2304')
|
||||||
const cellNode = gradebook.gradebookGrid.grid.getCellNode(0, columnIndex);
|
const cellNode = gradebook.gradebookGrid.grid.getCellNode(0, columnIndex)
|
||||||
notOk(cellNode.classList.contains('minimized'));
|
notOk(cellNode.classList.contains('minimized'))
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
|
@ -16,172 +16,199 @@
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import _ from 'underscore';
|
import _ from 'underscore'
|
||||||
import GradebookApi from 'jsx/gradezilla/default_gradebook/apis/GradebookApi';
|
import GradebookApi from 'jsx/gradezilla/default_gradebook/apis/GradebookApi'
|
||||||
|
|
||||||
QUnit.module('GradebookApi.createTeacherNotesColumn', {
|
QUnit.module('GradebookApi.createTeacherNotesColumn', {
|
||||||
setup () {
|
setup() {
|
||||||
this.customColumn = { id: '2401', hidden: false, position: 1, teacher_notes: true, title: 'Notes' };
|
this.customColumn = {
|
||||||
this.createTeacherNotesColumnUrl = '/api/v1/courses/1201/custom_gradebook_columns';
|
id: '2401',
|
||||||
this.server = sinon.fakeServer.create({ respondImmediately: true });
|
hidden: false,
|
||||||
const responseBody = JSON.stringify(this.customColumn);
|
position: 1,
|
||||||
this.server.respondWith('POST', this.createTeacherNotesColumnUrl, [200, { 'Content-Type': 'application/json' }, responseBody]);
|
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 () {
|
getRequest() {
|
||||||
// filter requests to eliminate spec pollution from unrelated specs
|
// 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 () {
|
teardown() {
|
||||||
this.server.restore();
|
this.server.restore()
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
test('sends a post request to the "create teacher notes column" url', function () {
|
test('sends a post request to the "create teacher notes column" url', function() {
|
||||||
return GradebookApi.createTeacherNotesColumn('1201')
|
return GradebookApi.createTeacherNotesColumn('1201').then(() => {
|
||||||
.then(() => {
|
const request = this.getRequest()
|
||||||
const request = this.getRequest();
|
equal(request.method, 'POST')
|
||||||
equal(request.method, 'POST');
|
equal(request.url, this.createTeacherNotesColumnUrl)
|
||||||
equal(request.url, this.createTeacherNotesColumnUrl);
|
})
|
||||||
});
|
})
|
||||||
});
|
|
||||||
|
|
||||||
test('includes data to create a teacher notes column', function () {
|
test('includes data to create a teacher notes column', function() {
|
||||||
return GradebookApi.createTeacherNotesColumn('1201')
|
return GradebookApi.createTeacherNotesColumn('1201').then(() => {
|
||||||
.then(() => {
|
const bodyData = JSON.parse(this.getRequest().requestBody)
|
||||||
const bodyData = JSON.parse(this.getRequest().requestBody);
|
equal(bodyData.column.title, 'Notes')
|
||||||
equal(bodyData.column.title, 'Notes');
|
strictEqual(bodyData.column.position, 1)
|
||||||
strictEqual(bodyData.column.position, 1);
|
equal(bodyData.column.teacher_notes, true)
|
||||||
equal(bodyData.column.teacher_notes, true);
|
})
|
||||||
});
|
})
|
||||||
});
|
|
||||||
|
|
||||||
test('includes required request headers', function () {
|
test('includes required request headers', function() {
|
||||||
return GradebookApi.createTeacherNotesColumn('1201')
|
return GradebookApi.createTeacherNotesColumn('1201').then(() => {
|
||||||
.then(() => {
|
const {requestHeaders} = this.getRequest()
|
||||||
const { requestHeaders } = this.getRequest();
|
ok(
|
||||||
ok(requestHeaders.Accept.includes('application/json+canvas-string-ids'), 'includes header for Canvas string ids');
|
requestHeaders.Accept.includes('application/json+canvas-string-ids'),
|
||||||
ok(requestHeaders['Content-Type'].includes('application/json'),
|
'includes header for Canvas string ids'
|
||||||
'includes "application/json" content type');
|
)
|
||||||
equal(requestHeaders['X-Requested-With'], 'XMLHttpRequest');
|
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 () {
|
test('sends the column data to the success handler', function() {
|
||||||
return GradebookApi.createTeacherNotesColumn('1201')
|
return GradebookApi.createTeacherNotesColumn('1201').then(({data}) => {
|
||||||
.then(({ data }) => {
|
deepEqual(data, this.customColumn)
|
||||||
deepEqual(data, this.customColumn);
|
})
|
||||||
});
|
})
|
||||||
});
|
|
||||||
|
|
||||||
QUnit.module('GradebookApi.updateTeacherNotesColumn', {
|
QUnit.module('GradebookApi.updateTeacherNotesColumn', {
|
||||||
setup () {
|
setup() {
|
||||||
this.customColumn = { id: '2401', hidden: true, position: 1, teacher_notes: true, title: 'Notes' };
|
this.customColumn = {id: '2401', hidden: true, position: 1, teacher_notes: true, title: 'Notes'}
|
||||||
this.updateTeacherNotesColumnUrl = '/api/v1/courses/1201/custom_gradebook_columns/2401';
|
this.updateTeacherNotesColumnUrl = '/api/v1/courses/1201/custom_gradebook_columns/2401'
|
||||||
this.server = sinon.fakeServer.create({ respondImmediately: true });
|
this.server = sinon.fakeServer.create({respondImmediately: true})
|
||||||
const responseBody = JSON.stringify(this.customColumn);
|
const responseBody = JSON.stringify(this.customColumn)
|
||||||
this.server.respondWith('PUT', this.updateTeacherNotesColumnUrl, [200, { 'Content-Type': 'application/json' }, responseBody]);
|
this.server.respondWith('PUT', this.updateTeacherNotesColumnUrl, [
|
||||||
|
200,
|
||||||
|
{'Content-Type': 'application/json'},
|
||||||
|
responseBody
|
||||||
|
])
|
||||||
},
|
},
|
||||||
|
|
||||||
getRequest () {
|
getRequest() {
|
||||||
// filter requests to eliminate spec pollution from unrelated specs
|
// 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 () {
|
teardown() {
|
||||||
this.server.restore();
|
this.server.restore()
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
test('sends a post request to the "create teacher notes column" url', function () {
|
test('sends a post request to the "create teacher notes column" url', function() {
|
||||||
return GradebookApi.updateTeacherNotesColumn('1201', '2401', { hidden: true })
|
return GradebookApi.updateTeacherNotesColumn('1201', '2401', {hidden: true}).then(() => {
|
||||||
.then(() => {
|
const request = this.getRequest()
|
||||||
const request = this.getRequest();
|
equal(request.method, 'PUT')
|
||||||
equal(request.method, 'PUT');
|
equal(request.url, this.updateTeacherNotesColumnUrl)
|
||||||
equal(request.url, this.updateTeacherNotesColumnUrl);
|
})
|
||||||
});
|
})
|
||||||
});
|
|
||||||
|
|
||||||
test('includes params for updating a teacher notes column', function () {
|
test('includes params for updating a teacher notes column', function() {
|
||||||
return GradebookApi.updateTeacherNotesColumn('1201', '2401', { hidden: true })
|
return GradebookApi.updateTeacherNotesColumn('1201', '2401', {hidden: true}).then(() => {
|
||||||
.then(() => {
|
const bodyData = JSON.parse(this.getRequest().requestBody)
|
||||||
const bodyData = JSON.parse(this.getRequest().requestBody);
|
equal(bodyData.column.hidden, true)
|
||||||
equal(bodyData.column.hidden, true);
|
})
|
||||||
});
|
})
|
||||||
});
|
|
||||||
|
|
||||||
test('includes required request headers', function () {
|
test('includes required request headers', function() {
|
||||||
return GradebookApi.updateTeacherNotesColumn('1201', '2401', { hidden: true })
|
return GradebookApi.updateTeacherNotesColumn('1201', '2401', {hidden: true}).then(() => {
|
||||||
.then(() => {
|
const {requestHeaders} = this.getRequest()
|
||||||
const { requestHeaders } = this.getRequest();
|
ok(
|
||||||
ok(requestHeaders.Accept.includes('application/json+canvas-string-ids'), 'includes header for Canvas string ids');
|
requestHeaders.Accept.includes('application/json+canvas-string-ids'),
|
||||||
ok(requestHeaders['Content-Type'].includes('application/json'),
|
'includes header for Canvas string ids'
|
||||||
'includes "application/json" content type');
|
)
|
||||||
equal(requestHeaders['X-Requested-With'], 'XMLHttpRequest');
|
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 () {
|
test('sends the column data to the success handler', function() {
|
||||||
return GradebookApi.updateTeacherNotesColumn('1201', '2401', { hidden: true })
|
return GradebookApi.updateTeacherNotesColumn('1201', '2401', {hidden: true}).then(({data}) => {
|
||||||
.then(({ data }) => {
|
deepEqual(data, this.customColumn)
|
||||||
deepEqual(data, this.customColumn);
|
})
|
||||||
});
|
})
|
||||||
});
|
|
||||||
|
|
||||||
QUnit.module('GradebookApi.updateSubmission', function (hooks) {
|
QUnit.module('GradebookApi.updateSubmission', function(hooks) {
|
||||||
const courseId = '1201';
|
const courseId = '1201'
|
||||||
const assignmentId = '303';
|
const assignmentId = '303'
|
||||||
const userId = '201';
|
const userId = '201'
|
||||||
const updateSubmissionUrl = `/api/v1/courses/${courseId}/assignments/${assignmentId}/submissions/${userId}`;
|
const updateSubmissionUrl = `/api/v1/courses/${courseId}/assignments/${assignmentId}/submissions/${userId}`
|
||||||
const submissionData = { all_submissions: [{ id: 301, late_policy_status: 'none' }] };
|
const submissionData = {all_submissions: [{id: 301, late_policy_status: 'none'}]}
|
||||||
let server;
|
let server
|
||||||
|
|
||||||
hooks.beforeEach(function () {
|
hooks.beforeEach(function() {
|
||||||
server = sinon.fakeServer.create({ respondImmediately: true });
|
server = sinon.fakeServer.create({respondImmediately: true})
|
||||||
const responseBody = JSON.stringify(submissionData);
|
const responseBody = JSON.stringify(submissionData)
|
||||||
server.respondWith('PUT', updateSubmissionUrl, [200, { 'Content-Type': 'application/json' }, responseBody]);
|
server.respondWith('PUT', updateSubmissionUrl, [
|
||||||
});
|
200,
|
||||||
|
{'Content-Type': 'application/json'},
|
||||||
|
responseBody
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
hooks.afterEach(function () {
|
hooks.afterEach(function() {
|
||||||
server.restore();
|
server.restore()
|
||||||
});
|
})
|
||||||
|
|
||||||
function getRequest () {
|
function getRequest() {
|
||||||
// filter requests to eliminate spec pollution from unrelated specs
|
// 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 () {
|
test('sends a put request to the "update submission" url', function() {
|
||||||
return GradebookApi.updateSubmission(courseId, assignmentId, userId, { latePolicyStatus: 'none' })
|
return GradebookApi.updateSubmission(courseId, assignmentId, userId, {
|
||||||
.then(() => {
|
latePolicyStatus: 'none'
|
||||||
const request = getRequest();
|
}).then(() => {
|
||||||
strictEqual(request.method, 'PUT');
|
const request = getRequest()
|
||||||
strictEqual(request.url, updateSubmissionUrl);
|
strictEqual(request.method, 'PUT')
|
||||||
});
|
strictEqual(request.url, updateSubmissionUrl)
|
||||||
});
|
})
|
||||||
|
})
|
||||||
|
|
||||||
test('includes params for updating a submission', function () {
|
test('includes params for updating a submission', function() {
|
||||||
return GradebookApi.updateSubmission(courseId, assignmentId, userId, { latePolicyStatus: 'none' })
|
return GradebookApi.updateSubmission(courseId, assignmentId, userId, {
|
||||||
.then(() => {
|
latePolicyStatus: 'none'
|
||||||
const bodyData = JSON.parse(getRequest().requestBody);
|
}).then(() => {
|
||||||
deepEqual(bodyData.submission.late_policy_status, 'none');
|
const bodyData = JSON.parse(getRequest().requestBody)
|
||||||
});
|
deepEqual(bodyData.submission.late_policy_status, 'none')
|
||||||
});
|
})
|
||||||
|
})
|
||||||
|
|
||||||
test('includes params to request visibility for the submission', function () {
|
test('includes params to request visibility for the submission', function() {
|
||||||
return GradebookApi.updateSubmission(courseId, assignmentId, userId, { latePolicyStatus: 'none' })
|
return GradebookApi.updateSubmission(courseId, assignmentId, userId, {
|
||||||
.then(() => {
|
latePolicyStatus: 'none'
|
||||||
const bodyData = JSON.parse(getRequest().requestBody);
|
}).then(() => {
|
||||||
strictEqual(bodyData.include.includes('visibility'), true);
|
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);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
test('sends the column data to the success handler', function() {
|
||||||
|
return GradebookApi.updateSubmission(courseId, assignmentId, userId, {
|
||||||
|
latePolicyStatus: 'none'
|
||||||
|
}).then(({data}) => {
|
||||||
|
deepEqual(data, submissionData)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
|
@ -16,14 +16,14 @@
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import _ from 'underscore';
|
import _ from 'underscore'
|
||||||
import {
|
import {
|
||||||
DEFAULT_LATE_POLICY_DATA,
|
DEFAULT_LATE_POLICY_DATA,
|
||||||
fetchLatePolicy,
|
fetchLatePolicy,
|
||||||
createLatePolicy,
|
createLatePolicy,
|
||||||
updateLatePolicy
|
updateLatePolicy
|
||||||
} from 'jsx/gradezilla/default_gradebook/apis/GradebookSettingsModalApi';
|
} from 'jsx/gradezilla/default_gradebook/apis/GradebookSettingsModalApi'
|
||||||
import { underscore } from 'convert_case';
|
import {underscore} from 'convert_case'
|
||||||
|
|
||||||
const latePolicyData = {
|
const latePolicyData = {
|
||||||
id: '15',
|
id: '15',
|
||||||
|
@ -34,128 +34,138 @@ const latePolicyData = {
|
||||||
lateSubmissionInterval: 'day',
|
lateSubmissionInterval: 'day',
|
||||||
lateSubmissionMinimumPercentEnabled: true,
|
lateSubmissionMinimumPercentEnabled: true,
|
||||||
lateSubmissionMinimumPercent: 40.0
|
lateSubmissionMinimumPercent: 40.0
|
||||||
};
|
}
|
||||||
|
|
||||||
function getRequestWithUrl (server, url) {
|
function getRequestWithUrl(server, url) {
|
||||||
// filter requests to eliminate spec pollution from unrelated specs
|
// 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', {
|
QUnit.module('GradebookSettingsModalApi.fetchLatePolicy success', {
|
||||||
setup () {
|
setup() {
|
||||||
this.url = '/api/v1/courses/19/late_policy';
|
this.url = '/api/v1/courses/19/late_policy'
|
||||||
this.server = sinon.fakeServer.create({ respondImmediately: true });
|
this.server = sinon.fakeServer.create({respondImmediately: true})
|
||||||
const responseBody = JSON.stringify({ late_policy: underscore(latePolicyData) });
|
const responseBody = JSON.stringify({late_policy: underscore(latePolicyData)})
|
||||||
this.server.respondWith('GET', this.url, [200, { 'Content-Type': 'application/json' }, responseBody]);
|
this.server.respondWith('GET', this.url, [
|
||||||
|
200,
|
||||||
|
{'Content-Type': 'application/json'},
|
||||||
|
responseBody
|
||||||
|
])
|
||||||
},
|
},
|
||||||
|
|
||||||
teardown () {
|
teardown() {
|
||||||
this.server.restore();
|
this.server.restore()
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
test('returns the late policy', function () {
|
test('returns the late policy', function() {
|
||||||
return fetchLatePolicy('19')
|
return fetchLatePolicy('19').then(({data}) => {
|
||||||
.then(({ data }) => {
|
deepEqual(data, {latePolicy: latePolicyData})
|
||||||
deepEqual(data, { latePolicy: latePolicyData });
|
})
|
||||||
});
|
})
|
||||||
});
|
|
||||||
|
|
||||||
QUnit.module('GradebookSettingsModalApi.fetchLatePolicy when late policy does not exist', {
|
QUnit.module('GradebookSettingsModalApi.fetchLatePolicy when late policy does not exist', {
|
||||||
setup () {
|
setup() {
|
||||||
this.url = '/api/v1/courses/19/late_policy';
|
this.url = '/api/v1/courses/19/late_policy'
|
||||||
this.server = sinon.fakeServer.create({ respondImmediately: true });
|
this.server = sinon.fakeServer.create({respondImmediately: true})
|
||||||
const responseBody = JSON.stringify(
|
const responseBody = JSON.stringify({
|
||||||
{ errors: [{ message: 'The specified resource does not exist.' }], error_report_id: '2199' }
|
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.server.respondWith('GET', this.url, [
|
||||||
|
404,
|
||||||
|
{'Content-Type': 'application/json'},
|
||||||
|
responseBody
|
||||||
|
])
|
||||||
},
|
},
|
||||||
|
|
||||||
teardown () {
|
teardown() {
|
||||||
this.server.restore();
|
this.server.restore()
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
test('returns default late policy data when the response is a 404', function () {
|
test('returns default late policy data when the response is a 404', function() {
|
||||||
return fetchLatePolicy('19')
|
return fetchLatePolicy('19').then(({data}) => {
|
||||||
.then(({ data }) => {
|
deepEqual(data, {latePolicy: DEFAULT_LATE_POLICY_DATA})
|
||||||
deepEqual(data, { latePolicy: DEFAULT_LATE_POLICY_DATA });
|
})
|
||||||
});
|
})
|
||||||
});
|
|
||||||
|
|
||||||
QUnit.module('GradebookSettingsModalApi.fetchLatePolicy when the request fails', {
|
QUnit.module('GradebookSettingsModalApi.fetchLatePolicy when the request fails', {
|
||||||
setup () {
|
setup() {
|
||||||
this.url = '/api/v1/courses/19/late_policy';
|
this.url = '/api/v1/courses/19/late_policy'
|
||||||
this.server = sinon.fakeServer.create({ respondImmediately: true });
|
this.server = sinon.fakeServer.create({respondImmediately: true})
|
||||||
this.server.respondWith('GET', this.url, [500, { 'Content-Type': 'application/json' }, JSON.stringify({})]);
|
this.server.respondWith('GET', this.url, [
|
||||||
|
500,
|
||||||
|
{'Content-Type': 'application/json'},
|
||||||
|
JSON.stringify({})
|
||||||
|
])
|
||||||
},
|
},
|
||||||
|
|
||||||
teardown () {
|
teardown() {
|
||||||
this.server.restore();
|
this.server.restore()
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
test('rejects the promise when the response is not a 200 or a 404', function () {
|
test('rejects the promise when the response is not a 200 or a 404', function() {
|
||||||
return fetchLatePolicy('19')
|
return fetchLatePolicy('19').catch(error => {
|
||||||
.catch((error) => {
|
strictEqual(error.response.status, 500)
|
||||||
strictEqual(error.response.status, 500);
|
})
|
||||||
});
|
})
|
||||||
});
|
|
||||||
|
|
||||||
QUnit.module('GradebookSettingsModalApi.createLatePolicy', {
|
QUnit.module('GradebookSettingsModalApi.createLatePolicy', {
|
||||||
setup () {
|
setup() {
|
||||||
this.latePolicyCreationData = { ...latePolicyData };
|
this.latePolicyCreationData = {...latePolicyData}
|
||||||
delete this.latePolicyCreationData.id;
|
delete this.latePolicyCreationData.id
|
||||||
this.url = '/api/v1/courses/19/late_policy';
|
this.url = '/api/v1/courses/19/late_policy'
|
||||||
this.server = sinon.fakeServer.create({ respondImmediately: true });
|
this.server = sinon.fakeServer.create({respondImmediately: true})
|
||||||
const responseBody = JSON.stringify({ late_policy: underscore(latePolicyData) });
|
const responseBody = JSON.stringify({late_policy: underscore(latePolicyData)})
|
||||||
this.server.respondWith('POST', this.url, [200, { 'Content-Type': 'application/json' }, responseBody]);
|
this.server.respondWith('POST', this.url, [
|
||||||
|
200,
|
||||||
|
{'Content-Type': 'application/json'},
|
||||||
|
responseBody
|
||||||
|
])
|
||||||
},
|
},
|
||||||
|
|
||||||
teardown () {
|
teardown() {
|
||||||
this.server.restore();
|
this.server.restore()
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
test('includes data to create a late_policy', function () {
|
test('includes data to create a late_policy', function() {
|
||||||
return createLatePolicy('19', latePolicyData)
|
return createLatePolicy('19', latePolicyData).then(() => {
|
||||||
.then(() => {
|
const bodyData = JSON.parse(getRequestWithUrl(this.server, this.url).requestBody)
|
||||||
const bodyData = JSON.parse(getRequestWithUrl(this.server, this.url).requestBody);
|
deepEqual(bodyData, {late_policy: underscore(latePolicyData)})
|
||||||
deepEqual(bodyData, { late_policy: underscore(latePolicyData) });
|
})
|
||||||
});
|
})
|
||||||
});
|
|
||||||
|
|
||||||
test('returns the late policy', function () {
|
test('returns the late policy', function() {
|
||||||
return createLatePolicy('19', this.latePolicyCreationData)
|
return createLatePolicy('19', this.latePolicyCreationData).then(({data}) => {
|
||||||
.then(({ data }) => {
|
deepEqual(data, {latePolicy: latePolicyData})
|
||||||
deepEqual(data, { latePolicy: latePolicyData });
|
})
|
||||||
});
|
})
|
||||||
});
|
|
||||||
|
|
||||||
QUnit.module('GradebookSettingsModalApi.updateLatePolicy', {
|
QUnit.module('GradebookSettingsModalApi.updateLatePolicy', {
|
||||||
setup () {
|
setup() {
|
||||||
this.url = '/api/v1/courses/19/late_policy';
|
this.url = '/api/v1/courses/19/late_policy'
|
||||||
this.changes = { lateSubmissionInterval: 'hour' };
|
this.changes = {lateSubmissionInterval: 'hour'}
|
||||||
this.server = sinon.fakeServer.create({ respondImmediately: true });
|
this.server = sinon.fakeServer.create({respondImmediately: true})
|
||||||
this.server.respondWith('PATCH', this.url, [204, {}, '']);
|
this.server.respondWith('PATCH', this.url, [204, {}, ''])
|
||||||
},
|
},
|
||||||
|
|
||||||
teardown () {
|
teardown() {
|
||||||
this.server.restore();
|
this.server.restore()
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
test('includes data to update a late_policy', function () {
|
test('includes data to update a late_policy', function() {
|
||||||
return updateLatePolicy('19', this.changes)
|
return updateLatePolicy('19', this.changes).then(() => {
|
||||||
.then(() => {
|
const bodyData = JSON.parse(getRequestWithUrl(this.server, this.url).requestBody)
|
||||||
const bodyData = JSON.parse(getRequestWithUrl(this.server, this.url).requestBody);
|
deepEqual(bodyData, {late_policy: underscore(this.changes)})
|
||||||
deepEqual(bodyData, { late_policy: underscore(this.changes) });
|
})
|
||||||
});
|
})
|
||||||
});
|
|
||||||
|
|
||||||
test('returns a 204 (successfully fulfilled request and no content)', function () {
|
test('returns a 204 (successfully fulfilled request and no content)', function() {
|
||||||
return updateLatePolicy('19', this.changes)
|
return updateLatePolicy('19', this.changes).then(({status}) => {
|
||||||
.then(({ status }) => {
|
equal(status, 204)
|
||||||
equal(status, 204);
|
})
|
||||||
});
|
})
|
||||||
});
|
|
||||||
|
|
|
@ -16,49 +16,49 @@
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { updateSubmissionComment } from 'jsx/gradezilla/default_gradebook/apis/SubmissionCommentApi';
|
import {updateSubmissionComment} from 'jsx/gradezilla/default_gradebook/apis/SubmissionCommentApi'
|
||||||
import { underscore } from 'convert_case';
|
import {underscore} from 'convert_case'
|
||||||
|
|
||||||
QUnit.module('SubmissionCommentApi.updateSubmissionComment', function (hooks) {
|
QUnit.module('SubmissionCommentApi.updateSubmissionComment', function(hooks) {
|
||||||
let server;
|
let server
|
||||||
const commentId = '12';
|
const commentId = '12'
|
||||||
const url = `/submission_comments/${commentId}`;
|
const url = `/submission_comments/${commentId}`
|
||||||
const updatedComment = 'an updated comment!';
|
const updatedComment = 'an updated comment!'
|
||||||
const editedAt = '2015-10-12T19:25:41Z';
|
const editedAt = '2015-10-12T19:25:41Z'
|
||||||
const submissionComment = {
|
const submissionComment = {
|
||||||
id: commentId,
|
id: commentId,
|
||||||
created_at: '2015-10-09T19:25:41Z',
|
created_at: '2015-10-09T19:25:41Z',
|
||||||
comment: updatedComment,
|
comment: updatedComment,
|
||||||
edited_at: editedAt
|
edited_at: editedAt
|
||||||
};
|
}
|
||||||
const responseBody = JSON.stringify({ submission_comment: underscore(submissionComment) });
|
const responseBody = JSON.stringify({submission_comment: underscore(submissionComment)})
|
||||||
|
|
||||||
hooks.beforeEach(function () {
|
hooks.beforeEach(function() {
|
||||||
server = sinon.fakeServer.create({ respondImmediately: true });
|
server = sinon.fakeServer.create({respondImmediately: true})
|
||||||
});
|
})
|
||||||
|
|
||||||
hooks.afterEach(function () {
|
hooks.afterEach(function() {
|
||||||
server.restore();
|
server.restore()
|
||||||
});
|
})
|
||||||
|
|
||||||
test('on success, returns the submission comment with the updated comment', function () {
|
test('on success, returns the submission comment with the updated comment', function() {
|
||||||
server.respondWith('PUT', url, [200, { 'Content-Type': 'application/json' }, responseBody]);
|
server.respondWith('PUT', url, [200, {'Content-Type': 'application/json'}, responseBody])
|
||||||
return updateSubmissionComment(commentId, updatedComment).then((response) => {
|
return updateSubmissionComment(commentId, updatedComment).then(response => {
|
||||||
strictEqual(response.data.comment, updatedComment);
|
strictEqual(response.data.comment, updatedComment)
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
||||||
test('on success, returns the submission comment with an updated editedAt', function () {
|
test('on success, returns the submission comment with an updated editedAt', function() {
|
||||||
server.respondWith('PUT', url, [200, { 'Content-Type': 'application/json' }, responseBody]);
|
server.respondWith('PUT', url, [200, {'Content-Type': 'application/json'}, responseBody])
|
||||||
return updateSubmissionComment(commentId, updatedComment).then((response) => {
|
return updateSubmissionComment(commentId, updatedComment).then(response => {
|
||||||
strictEqual(response.data.editedAt.getTime(), new Date(editedAt).getTime());
|
strictEqual(response.data.editedAt.getTime(), new Date(editedAt).getTime())
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
||||||
test('on failure, returns a rejected promise with the error', function () {
|
test('on failure, returns a rejected promise with the error', function() {
|
||||||
server.respondWith('PUT', url, [500, { 'Content-Type': 'application/json' }, JSON.stringify({})]);
|
server.respondWith('PUT', url, [500, {'Content-Type': 'application/json'}, JSON.stringify({})])
|
||||||
return updateSubmissionComment(commentId, updatedComment).catch((error) => {
|
return updateSubmissionComment(commentId, updatedComment).catch(error => {
|
||||||
strictEqual(error.response.status, 500);
|
strictEqual(error.response.status, 500)
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
|
@ -17,7 +17,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import DataLoader from 'jsx/gradezilla/DataLoader'
|
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 {createExampleStudents} from './DataLoadingSpecHelpers'
|
||||||
import DataLoadingWrapper from './DataLoadingWrapper'
|
import DataLoadingWrapper from './DataLoadingWrapper'
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import DataLoader from 'jsx/gradezilla/DataLoader'
|
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 {createExampleStudents} from './DataLoadingSpecHelpers'
|
||||||
import DataLoadingWrapper from './DataLoadingWrapper'
|
import DataLoadingWrapper from './DataLoadingWrapper'
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import DataLoader from 'jsx/gradezilla/DataLoader'
|
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 {createExampleStudents} from './DataLoadingSpecHelpers'
|
||||||
import DataLoadingWrapper from './DataLoadingWrapper'
|
import DataLoadingWrapper from './DataLoadingWrapper'
|
||||||
|
|
||||||
|
|
|
@ -16,94 +16,96 @@
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash'
|
||||||
import StudentDatastore from 'jsx/gradezilla/default_gradebook/stores/StudentDatastore';
|
import StudentDatastore from 'jsx/gradezilla/default_gradebook/stores/StudentDatastore'
|
||||||
|
|
||||||
QUnit.module('StudentDatastore', function (hooks) {
|
QUnit.module('StudentDatastore', function(hooks) {
|
||||||
let studentDatastore;
|
let studentDatastore
|
||||||
let userStudentMap;
|
let userStudentMap
|
||||||
let testStudentMap;
|
let testStudentMap
|
||||||
|
|
||||||
hooks.beforeEach(function () {
|
hooks.beforeEach(function() {
|
||||||
userStudentMap = {};
|
userStudentMap = {}
|
||||||
testStudentMap = {};
|
testStudentMap = {}
|
||||||
studentDatastore = new StudentDatastore(userStudentMap, testStudentMap);
|
studentDatastore = new StudentDatastore(userStudentMap, testStudentMap)
|
||||||
});
|
})
|
||||||
|
|
||||||
QUnit.module('#listStudentIds');
|
QUnit.module('#listStudentIds')
|
||||||
|
|
||||||
test('returns the definitive list of known students', function () {
|
test('returns the definitive list of known students', function() {
|
||||||
const studentIds = ['1101', '1102', '1103'];
|
const studentIds = ['1101', '1102', '1103']
|
||||||
studentDatastore.setStudentIds(studentIds);
|
studentDatastore.setStudentIds(studentIds)
|
||||||
const storedStudentIds = studentDatastore.listStudentIds();
|
const storedStudentIds = studentDatastore.listStudentIds()
|
||||||
strictEqual(storedStudentIds.length, 3, 'datastore contains 3 students');
|
strictEqual(storedStudentIds.length, 3, 'datastore contains 3 students')
|
||||||
deepEqual(storedStudentIds, studentIds);
|
deepEqual(storedStudentIds, studentIds)
|
||||||
});
|
})
|
||||||
|
|
||||||
QUnit.module('#setStudentIds');
|
QUnit.module('#setStudentIds')
|
||||||
|
|
||||||
test('removes stored user students not represented in the list of student ids', function () {
|
test('removes stored user students not represented in the list of student ids', function() {
|
||||||
const students = [{ id: '1103' }, { id: '1101' }, { id: '1102' }];
|
const students = [{id: '1103'}, {id: '1101'}, {id: '1102'}]
|
||||||
studentDatastore.addUserStudents(students);
|
studentDatastore.addUserStudents(students)
|
||||||
studentDatastore.setStudentIds(['1102']);
|
studentDatastore.setStudentIds(['1102'])
|
||||||
const storedStudents = studentDatastore.listStudents();
|
const storedStudents = studentDatastore.listStudents()
|
||||||
strictEqual(storedStudents.length, 1, 'datastore contains 1 student');
|
strictEqual(storedStudents.length, 1, 'datastore contains 1 student')
|
||||||
equal(storedStudents[0].id, '1102');
|
equal(storedStudents[0].id, '1102')
|
||||||
});
|
})
|
||||||
|
|
||||||
test('removes stored test students not represented in the list of student ids', function () {
|
test('removes stored test students not represented in the list of student ids', function() {
|
||||||
const students = [{ id: '1103' }, { id: '1101' }, { id: '1102' }];
|
const students = [{id: '1103'}, {id: '1101'}, {id: '1102'}]
|
||||||
studentDatastore.addTestStudents(students);
|
studentDatastore.addTestStudents(students)
|
||||||
studentDatastore.setStudentIds(['1102']);
|
studentDatastore.setStudentIds(['1102'])
|
||||||
const storedStudents = studentDatastore.listStudents();
|
const storedStudents = studentDatastore.listStudents()
|
||||||
strictEqual(storedStudents.length, 1, 'datastore contains 1 student');
|
strictEqual(storedStudents.length, 1, 'datastore contains 1 student')
|
||||||
equal(storedStudents[0].id, '1102');
|
equal(storedStudents[0].id, '1102')
|
||||||
});
|
})
|
||||||
|
|
||||||
QUnit.module('#listStudents');
|
QUnit.module('#listStudents')
|
||||||
|
|
||||||
test('returns the students stored in order of the saved student ids', function () {
|
test('returns the students stored in order of the saved student ids', function() {
|
||||||
const students = [{ id: '1103' }, { id: '1101' }, { id: '1102' }];
|
const students = [{id: '1103'}, {id: '1101'}, {id: '1102'}]
|
||||||
studentDatastore.addUserStudents(students);
|
studentDatastore.addUserStudents(students)
|
||||||
studentDatastore.setStudentIds(['1101', '1102', '1103']);
|
studentDatastore.setStudentIds(['1101', '1102', '1103'])
|
||||||
const storedStudents = studentDatastore.listStudents();
|
const storedStudents = studentDatastore.listStudents()
|
||||||
strictEqual(storedStudents.length, 3, 'datastore contains 3 students');
|
strictEqual(storedStudents.length, 3, 'datastore contains 3 students')
|
||||||
deepEqual(storedStudents, _.sortBy(students, 'id'));
|
deepEqual(storedStudents, _.sortBy(students, 'id'))
|
||||||
});
|
})
|
||||||
|
|
||||||
test('includes test students', function () {
|
test('includes test students', function() {
|
||||||
const students = [{ id: '1103' }, { id: '1101' }, { id: '1102' }];
|
const students = [{id: '1103'}, {id: '1101'}, {id: '1102'}]
|
||||||
studentDatastore.addUserStudents(students.slice(0, 2));
|
studentDatastore.addUserStudents(students.slice(0, 2))
|
||||||
studentDatastore.addTestStudents(students.slice(2, 3));
|
studentDatastore.addTestStudents(students.slice(2, 3))
|
||||||
studentDatastore.setStudentIds(['1101', '1102', '1103']);
|
studentDatastore.setStudentIds(['1101', '1102', '1103'])
|
||||||
const storedStudents = studentDatastore.listStudents();
|
const storedStudents = studentDatastore.listStudents()
|
||||||
strictEqual(storedStudents.length, 3, 'datastore contains 3 students');
|
strictEqual(storedStudents.length, 3, 'datastore contains 3 students')
|
||||||
deepEqual(storedStudents, _.sortBy(students, 'id'));
|
deepEqual(storedStudents, _.sortBy(students, 'id'))
|
||||||
});
|
})
|
||||||
|
|
||||||
test('includes students stored directly into the original userStudentMap', function () {
|
test('includes students stored directly into the original userStudentMap', function() {
|
||||||
studentDatastore.setStudentIds(['1101', '1102', '1103']);
|
studentDatastore.setStudentIds(['1101', '1102', '1103'])
|
||||||
const students = [{ id: '1103' }, { id: '1101' }, { id: '1102' }];
|
const students = [{id: '1103'}, {id: '1101'}, {id: '1102'}]
|
||||||
Object.assign(userStudentMap, _.keyBy(students, 'id'));
|
Object.assign(userStudentMap, _.keyBy(students, 'id'))
|
||||||
const storedStudents = studentDatastore.listStudents();
|
const storedStudents = studentDatastore.listStudents()
|
||||||
strictEqual(storedStudents.length, 3, 'datastore contains 3 students');
|
strictEqual(storedStudents.length, 3, 'datastore contains 3 students')
|
||||||
deepEqual(storedStudents, _.sortBy(students, 'id'));
|
deepEqual(storedStudents, _.sortBy(students, 'id'))
|
||||||
});
|
})
|
||||||
|
|
||||||
test('includes students stored directly into the original testStudentMap', function () {
|
test('includes students stored directly into the original testStudentMap', function() {
|
||||||
studentDatastore.setStudentIds(['1101', '1102', '1103']);
|
studentDatastore.setStudentIds(['1101', '1102', '1103'])
|
||||||
const students = [{ id: '1103' }, { id: '1101' }, { id: '1102' }];
|
const students = [{id: '1103'}, {id: '1101'}, {id: '1102'}]
|
||||||
Object.assign(testStudentMap, _.keyBy(students, 'id'));
|
Object.assign(testStudentMap, _.keyBy(students, 'id'))
|
||||||
const storedStudents = studentDatastore.listStudents();
|
const storedStudents = studentDatastore.listStudents()
|
||||||
strictEqual(storedStudents.length, 3, 'datastore contains 3 students');
|
strictEqual(storedStudents.length, 3, 'datastore contains 3 students')
|
||||||
deepEqual(storedStudents, _.sortBy(students, 'id'));
|
deepEqual(storedStudents, _.sortBy(students, 'id'))
|
||||||
});
|
})
|
||||||
|
|
||||||
test('includes placeholder students for student ids not matching a stored student object', function () {
|
test('includes placeholder students for student ids not matching a stored student object', function() {
|
||||||
const students = [{ id: '1103' }, { id: '1101' }];
|
const students = [{id: '1103'}, {id: '1101'}]
|
||||||
studentDatastore.addUserStudents(students);
|
studentDatastore.addUserStudents(students)
|
||||||
studentDatastore.setStudentIds(['1101', '1102', '1103']);
|
studentDatastore.setStudentIds(['1101', '1102', '1103'])
|
||||||
const placeholderStudent = studentDatastore.listStudents().find(student => student.id === '1102');
|
const placeholderStudent = studentDatastore
|
||||||
strictEqual(placeholderStudent.isPlaceholder, true);
|
.listStudents()
|
||||||
});
|
.find(student => student.id === '1102')
|
||||||
});
|
strictEqual(placeholderStudent.isPlaceholder, true)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
|
@ -31,11 +31,7 @@ QUnit.module('AssignmentMuterDialogManager', suiteHooks => {
|
||||||
})
|
})
|
||||||
|
|
||||||
function createManager() {
|
function createManager() {
|
||||||
return new AssignmentMuterDialogManager(
|
return new AssignmentMuterDialogManager(assignment, url, submissionsLoaded)
|
||||||
assignment,
|
|
||||||
url,
|
|
||||||
submissionsLoaded
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QUnit.module('#assignment', () => {
|
QUnit.module('#assignment', () => {
|
||||||
|
|
|
@ -16,82 +16,82 @@
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* 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('EnterGradesAsSetting', () => {
|
||||||
QUnit.module('.defaultOptionForGradingType', () => {
|
QUnit.module('.defaultOptionForGradingType', () => {
|
||||||
test('is "points" for the "points" grading type', () => {
|
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', () => {
|
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', () => {
|
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', () => {
|
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', () => {
|
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', () => {
|
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', () => {
|
QUnit.module('.optionsForGradingType', () => {
|
||||||
test('includes "points" for the "points" grading type', () => {
|
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', () => {
|
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', () => {
|
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', () => {
|
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', () => {
|
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', () => {
|
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', () => {
|
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', () => {
|
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', () => {
|
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', () => {
|
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', () => {
|
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', () => {
|
test('do not exist for the "not_graded" grading type', () => {
|
||||||
deepEqual(EnterGradesAsSetting.optionsForGradingType('not_graded'), []);
|
deepEqual(EnterGradesAsSetting.optionsForGradingType('not_graded'), [])
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
|
@ -16,49 +16,49 @@
|
||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* 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) {
|
QUnit.module('TextMeasure', function(hooks) {
|
||||||
let $fixture;
|
let $fixture
|
||||||
|
|
||||||
hooks.beforeEach(function () {
|
hooks.beforeEach(function() {
|
||||||
$fixture = document.createElement('div');
|
$fixture = document.createElement('div')
|
||||||
document.body.appendChild($fixture);
|
document.body.appendChild($fixture)
|
||||||
|
|
||||||
$fixture.innerHTML = '<div id="content"></div>';
|
$fixture.innerHTML = '<div id="content"></div>'
|
||||||
});
|
})
|
||||||
|
|
||||||
hooks.afterEach(function () {
|
hooks.afterEach(function() {
|
||||||
$fixture.remove();
|
$fixture.remove()
|
||||||
});
|
})
|
||||||
|
|
||||||
QUnit.module('getWidth', function () {
|
QUnit.module('getWidth', function() {
|
||||||
test('returns a numerical width for the given text', function () {
|
test('returns a numerical width for the given text', function() {
|
||||||
const width = TextMeasure.getWidth('example');
|
const width = TextMeasure.getWidth('example')
|
||||||
equal(typeof width, 'number');
|
equal(typeof width, 'number')
|
||||||
});
|
})
|
||||||
|
|
||||||
test('returns integers', function () {
|
test('returns integers', function() {
|
||||||
const width = TextMeasure.getWidth('example');
|
const width = TextMeasure.getWidth('example')
|
||||||
strictEqual(width, Math.floor(width));
|
strictEqual(width, Math.floor(width))
|
||||||
});
|
})
|
||||||
|
|
||||||
test('returns larger numbers for wider text', function () {
|
test('returns larger numbers for wider text', function() {
|
||||||
const orderedWords = ['a', 'aa', 'aaa'];
|
const orderedWords = ['a', 'aa', 'aaa']
|
||||||
const orderedWidths = ['aaa', 'a', 'aa'].map(TextMeasure.getWidth).sort();
|
const orderedWidths = ['aaa', 'a', 'aa'].map(TextMeasure.getWidth).sort()
|
||||||
deepEqual(orderedWidths, orderedWords.map(TextMeasure.getWidth));
|
deepEqual(orderedWidths, orderedWords.map(TextMeasure.getWidth))
|
||||||
});
|
})
|
||||||
|
|
||||||
test('creates a "text-measure" element attached to the "content" element', function () {
|
test('creates a "text-measure" element attached to the "content" element', function() {
|
||||||
TextMeasure.getWidth('example');
|
TextMeasure.getWidth('example')
|
||||||
const $textMeasure = document.getElementById('text-measure');
|
const $textMeasure = document.getElementById('text-measure')
|
||||||
equal($textMeasure.parentElement, document.getElementById('content'));
|
equal($textMeasure.parentElement, document.getElementById('content'))
|
||||||
});
|
})
|
||||||
|
|
||||||
test('creates only one "text-measure" element', function () {
|
test('creates only one "text-measure" element', function() {
|
||||||
TextMeasure.getWidth('example');
|
TextMeasure.getWidth('example')
|
||||||
TextMeasure.getWidth('sample');
|
TextMeasure.getWidth('sample')
|
||||||
strictEqual(document.getElementById('content').children.length, 1);
|
strictEqual(document.getElementById('content').children.length, 1)
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
Loading…
Reference in New Issue