diff --git a/app/coffeescripts/AssignmentMuter.coffee b/app/coffeescripts/AssignmentMuter.coffee
index f863b4b200b..e282f8e981b 100644
--- a/app/coffeescripts/AssignmentMuter.coffee
+++ b/app/coffeescripts/AssignmentMuter.coffee
@@ -9,12 +9,15 @@ define [
], (I18n, $, mute_dialog_template) ->
class AssignmentMuter
- constructor: (@$link, @assignment, @url, @setter) ->
- @$link = $(@$link)
- @updateLink()
- @$link.click (event) =>
- event.preventDefault()
+ constructor: (@$link, @assignment, @url, @setter, @options) ->
+ if @options?.openDialogInstantly
if @assignment.muted then @confirmUnmute() else @showDialog()
+ else
+ @$link = $(@$link)
+ @updateLink()
+ @$link.click (event) =>
+ event.preventDefault()
+ if @assignment.muted then @confirmUnmute() else @showDialog()
updateLink: =>
@$link.text(if @assignment.muted then I18n.t('unmute_assignment', 'Unmute Assignment') else I18n.t('mute_assignment', 'Mute Assignment'))
@@ -37,7 +40,7 @@ define [
@setter @assignment, 'muted', serverResponse.assignment.muted
else
@assignment.muted = serverResponse.assignment.muted
- @updateLink()
+ @updateLink() unless @options?.openDialogInstantly
@$dialog.dialog('close')
$.publish('assignment_muting_toggled', [@assignment])
diff --git a/app/jsx/gradebook/grid/actions/assignmentGroupsActions.jsx b/app/jsx/gradebook/grid/actions/assignmentGroupsActions.jsx
index f0eaaa8d50e..7b2cb73f2ba 100644
--- a/app/jsx/gradebook/grid/actions/assignmentGroupsActions.jsx
+++ b/app/jsx/gradebook/grid/actions/assignmentGroupsActions.jsx
@@ -4,7 +4,8 @@ define([
], function (Reflux, $) {
var AssignmentGroupsActions = Reflux.createActions({
load: { asyncResult: true },
- replaceAssignmentGroups: { asyncResult: false }
+ replaceAssignmentGroups: { asyncResult: false },
+ replaceAssignment: {asyncResult: false}
});
AssignmentGroupsActions.load.listen(function() {
diff --git a/app/jsx/gradebook/grid/components/column_types/headerRenderer.jsx b/app/jsx/gradebook/grid/components/column_types/headerRenderer.jsx
index dc390a4d70a..18a9ad3fc95 100644
--- a/app/jsx/gradebook/grid/components/column_types/headerRenderer.jsx
+++ b/app/jsx/gradebook/grid/components/column_types/headerRenderer.jsx
@@ -70,10 +70,14 @@ define([
label = this.props.label;
if (assignment) {
- var paddingAdjustment = GradebookConstants.DEFAULT_LAYOUTS.headers.paddingAdjustment;
+ var paddingAdjustment = GradebookConstants.DEFAULT_LAYOUTS.headers.paddingAdjustment,
+ className = "assignment-name" + ((assignment.muted) ? ' muted' : '');
+
return (
-
+
{ this.shouldDisplayAssignmentWarning() && }
{label}
diff --git a/app/jsx/gradebook/grid/components/dropdown_components/assignmentHeaderDropdownOptions.jsx b/app/jsx/gradebook/grid/components/dropdown_components/assignmentHeaderDropdownOptions.jsx
index 07441626bb1..bd41d86d718 100644
--- a/app/jsx/gradebook/grid/components/dropdown_components/assignmentHeaderDropdownOptions.jsx
+++ b/app/jsx/gradebook/grid/components/dropdown_components/assignmentHeaderDropdownOptions.jsx
@@ -5,8 +5,9 @@ define([
'i18n!gradebook',
'jsx/gradebook/grid/components/dropdown_components/headerDropdownOption',
'jsx/gradebook/grid/constants',
- 'jsx/gradebook/grid/components/dropdown_components/setDefaultGradeOption'
-], function (React, _, I18n, HeaderDropdownOption, GradebookConstants, SetDefaultGradeOption) {
+ 'jsx/gradebook/grid/components/dropdown_components/setDefaultGradeOption',
+ 'jsx/gradebook/grid/components/dropdown_components/muteAssignmentOption'
+], function (React, _, I18n, HeaderDropdownOption, GradebookConstants, SetDefaultGradeOption, MuteAssignmentOption) {
var AssignmentHeaderDropdownOptions = React.createClass({
@@ -46,9 +47,6 @@ define([
dropdownOptions.splice(1, 0, speedGraderOption);
}
- muteAssignmentOption = { title: I18n.t('Mute Assignment'), action: 'toggleMuting' };
- if (assignment.muted) muteAssignmentOption.title = I18n.t('Unmute Assignment');
- dropdownOptions.push(muteAssignmentOption);
return dropdownOptions;
},
@@ -83,6 +81,10 @@ define([
}
})
}
+
+
);
}
diff --git a/app/jsx/gradebook/grid/components/dropdown_components/muteAssignmentOption.jsx b/app/jsx/gradebook/grid/components/dropdown_components/muteAssignmentOption.jsx
new file mode 100644
index 00000000000..0df63950303
--- /dev/null
+++ b/app/jsx/gradebook/grid/components/dropdown_components/muteAssignmentOption.jsx
@@ -0,0 +1,62 @@
+
+/** @jsx React.DOM */
+define([
+ 'react',
+ 'jquery',
+ 'bower/reflux/dist/reflux',
+ 'underscore',
+ 'i18n!gradebook',
+ 'jsx/gradebook/grid/components/dropdown_components/headerDropdownOption',
+ 'compiled/AssignmentMuter',
+ 'jsx/gradebook/grid/constants',
+ 'jsx/gradebook/grid/actions/assignmentGroupsActions'
+], function (
+ React,
+ $,
+ Reflux,
+ _,
+ I18n,
+ HeaderDropdownOption,
+ AssignmentMuter,
+ GradebookConstants,
+ AssignmentGroupsActions
+) {
+
+ const MUTE = I18n.t('Mute Assignment'),
+ UNMUTE = I18n.t('Unmute Assignment'),
+ MUTING_EVENT = 'assignment_muting_toggled';
+
+ var MuteAssignmentOption = React.createClass({
+
+ propTypes: {
+ assignment: React.PropTypes.object.isRequired
+ },
+
+ openDialog() {
+ var assignment = this.props.assignment,
+ contextUrl = GradebookConstants.context_url,
+ options = {openDialogInstantly: true},
+ id = assignment.id,
+ url = contextUrl + "/assignments/" + id + "/mute";
+
+ new AssignmentMuter(null, assignment, url, null, options);
+
+ $.subscribe(MUTING_EVENT, (assignment) => {
+ AssignmentGroupsActions.replaceAssignment(assignment);
+ $.unsubscribe(MUTING_EVENT);
+ });
+ },
+
+ render() {
+ var title = (this.props.assignment.muted) ? UNMUTE : MUTE;
+ return(
+
+ );
+ }
+ });
+
+ return MuteAssignmentOption;
+});
diff --git a/app/jsx/gradebook/grid/components/gradebook.jsx b/app/jsx/gradebook/grid/components/gradebook.jsx
index d00bfd23deb..e9ae02e4ace 100644
--- a/app/jsx/gradebook/grid/components/gradebook.jsx
+++ b/app/jsx/gradebook/grid/components/gradebook.jsx
@@ -21,7 +21,8 @@ define([
'../actions/submissionsActions',
'../stores/keyboardNavigationStore',
'../actions/keyboardNavigationActions',
- '../helpers/columnArranger'
+ '../helpers/columnArranger',
+ 'vendor/spin'
], function (
React,
FixedDataTable,
@@ -44,12 +45,14 @@ define([
SubmissionsActions,
KeyboardNavigationStore,
KeyboardNavigationActions,
- ColumnArranger
+ ColumnArranger,
+ Spinner
){
var Table = FixedDataTable.Table,
Column = FixedDataTable.Column,
- isColumnResizing = false;
+ isColumnResizing = false,
+ spinner;
var Gradebook = React.createClass({
mixins: [
@@ -215,6 +218,15 @@ define([
|| this.state.submissions.error;
},
+ renderSpinner() {
+ spinner = new Spinner();
+ $(spinner.spin().el).css({
+ opacity: 0.5,
+ top: '55px',
+ left: '50%'
+ }).addClass('use-css-transitions-for-show-hide').appendTo('#main');
+ },
+
renderNotesColumn() {
if (!this.state.toolbarOptions.hideNotesColumn) {
return this.renderColumn(I18n.t('Notes'), GradebookConstants.NOTES_COLUMN_ID);
@@ -242,6 +254,9 @@ define([
}
else if (this.state.submissions.data && this.state.assignmentGroups.data
&& this.state.studentEnrollments.data) {
+
+ $(spinner.el).remove();
+
return (
);
} else {
- return (
{I18n.t('Gradebook loading...replace this with a spinner?')}
);
+ if (!spinner) {
+ this.renderSpinner();
+ }
+
+ return
;
}
}
});
diff --git a/app/jsx/gradebook/grid/stores/assignmentGroupsStore.jsx b/app/jsx/gradebook/grid/stores/assignmentGroupsStore.jsx
index c9ec5ddb6c8..cf91fa9ea48 100644
--- a/app/jsx/gradebook/grid/stores/assignmentGroupsStore.jsx
+++ b/app/jsx/gradebook/grid/stores/assignmentGroupsStore.jsx
@@ -44,6 +44,16 @@ define([
});
},
+ onReplaceAssignment(updatedAssignment) {
+ var assignmentGroups = this.assignmentGroups.data,
+ assignments = _.flatten(_.pluck(assignmentGroups, 'assignments')),
+ assignment = _.find(assignments, assignment => updatedAssignment.id === assignment.id);
+
+ assignment.muted = updatedAssignment.muted;
+ this.assignmentGroups.data = assignmentGroups;
+ this.trigger(this.assignmentGroups);
+ },
+
formatAssignmentGroups(groups) {
return _.map(groups, (group) => {
group.assignments = _.map(
diff --git a/spec/coffeescripts/jsx/gradebook/grid/components/dropdown_components/muteAssignmentOptionSpec.coffee b/spec/coffeescripts/jsx/gradebook/grid/components/dropdown_components/muteAssignmentOptionSpec.coffee
new file mode 100644
index 00000000000..7912e811f3a
--- /dev/null
+++ b/spec/coffeescripts/jsx/gradebook/grid/components/dropdown_components/muteAssignmentOptionSpec.coffee
@@ -0,0 +1,62 @@
+define [
+ 'jsx/gradebook/grid/components/dropdown_components/muteAssignmentOption',
+ 'compiled/gradebook2/SetDefaultGradeDialog'
+ 'jquery'
+], (SetDefaultGradeOption, SetDefaultGradeDialog, $) ->
+
+ wrapper = document.getElementById('fixtures')
+
+ defaultProps = ->
+ assignment: { id: '1', muted: false }
+
+ renderComponent = (props) ->
+ props = props || defaultProps()
+ componentFactory = React.createFactory(SetDefaultGradeOption)
+ React.render(componentFactory(props), wrapper)
+
+ module 'MuteAssignmentOption',
+ setup: ->
+ $('.ui-dialog').remove()
+ @component = renderComponent()
+ teardown: ->
+ $('.ui-dialog').remove()
+ React.unmountComponentAtNode wrapper
+
+ test 'mounts properly', ->
+ ok renderComponent().isMounted()
+
+ test 'displays "Mute Assignment" when assignment is unmuted', ->
+ component = renderComponent()
+ text = component.getDOMNode().children[0].innerHTML
+ deepEqual(text, 'Mute Assignment')
+
+ test 'displays "Unmute Assignment" when assignment is muted', ->
+ props = {assignment: {id: '1', muted: true}}
+ component = renderComponent(props)
+ text = component.getDOMNode().children[0].innerHTML
+ deepEqual(text, 'Unmute Assignment')
+
+ test 'displays dialog on click', ->
+ component = renderComponent()
+ equal($('.ui-dialog').size(), 0)
+ component.openDialog()
+ equal($('.ui-dialog').size(), 1)
+
+ test 'mute dialog displays when assignment is unmuted', ->
+ component = renderComponent()
+ component.openDialog()
+ title = $('.ui-dialog-title')[0].innerHTML
+ equal(title, 'Mute Assignment')
+
+ test 'unmute dialog displays when assignment is muted', ->
+ props = {assignment: {id: '1', muted: true}}
+ component = renderComponent(props)
+ component.openDialog()
+ title = $('.ui-dialog-title')[0].innerHTML
+ equal(title, 'Unmute Assignment')
+
+ test '$subscribe to assignment_muting_toggled event after dialog is opened', ->
+ subscribeStub = @stub($, 'subscribe')
+ component = renderComponent()
+ component.openDialog()
+ ok subscribeStub.calledWith('assignment_muting_toggled')