show correct info when adding multiple grading schemes

when adding multiple grading schemes without refreshing the
page, the information should show up correctly. also, when
editing a scheme, you should not be able to edit, trash, or
add any new schemes (until you've saved or cancelled editing).
i also did some refactoring and split up the TabContainer file
into two new components: GradingStandardContainer and
GradingPeriodContainer.

closes CNVS-18481

test plan:
1. Go to the grading standards page for a course or an account
(/courses/:course_id/grading_standards or
/accounts/:account_id/grading_standards)

2. Click the 'Add grading scheme' button. Verify that the
button is grayed out and disabled after you click it. Also verify
that the 'pencil' and 'trash' icons are not present on the scheme
while you are editing it. Enter a new name for the grading scheme
and change some of the row values, delete a few rows, etc. Then click
'Save'. Verify after clicking 'Save' that the 'Add grading scheme'
button is un-grayed out and re-enabled.

3. Click the 'Add grading scheme' button again. Verify that
the title and data of the _first_ grading scheme you created
(listed below the one you're creating now) is still accurate.
Enter in some custom data for the new scheme and then hit 'Save'.
After hitting save, make sure both schemes show accurate information.

4. Refresh the page and make sure accurate data is still showing
up.

5. Whenever a grading scheme is being edited, verify that clicking
	edit or trash icons on other schemes does not do anything. The
	icons of other schemes should be disabled when you are editing
	a scheme.

6. Whenever a grading scheme is being edited, verify that the
	'Add grading scheme' button is grayed out/disabled.

7. Click the 'Add Grading Scheme' button and then, without
	clicking 'Save' or 'Cancel', refresh the page. The scheme
	that was just added should not be present, since it was
	never saved.

Change-Id: I07f662729022a5d2ea4569fcbd8774147b4e2eee
Reviewed-on: https://gerrit.instructure.com/48697
Tested-by: Jenkins
Reviewed-by: Cameron Sutter <csutter@instructure.com>
Product-Review: Spencer Olson <solson@instructure.com>
QA-Review: Amber Taniuchi <amber@instructure.com>
This commit is contained in:
Spencer Olson 2015-02-11 13:54:25 -06:00
parent a1315792db
commit d5afa47968
11 changed files with 368 additions and 297 deletions

View File

@ -1 +1 @@
require ['jsx/grading/tab_container']
require ['jsx/grading/tabContainer']

View File

@ -30,7 +30,8 @@ class GradingStandardsController < ApplicationController
js_env({
:GRADING_STANDARDS_URL => context_url(@context, :context_grading_standards_url),
:GRADING_PERIODS_URL => context_url(@context, :api_v1_context_grading_periods_url),
:MULTIPLE_GRADING_PERIODS => multiple_grading_periods?
:MULTIPLE_GRADING_PERIODS => multiple_grading_periods?,
:DEFAULT_DATA => default_data
})
@standards = GradingStandard.standards_for(@context).sorted.limit(100)
respond_to do |format|
@ -52,7 +53,7 @@ class GradingStandardsController < ApplicationController
@standard.user = @current_user
respond_to do |format|
if @standard.save
format.json{ render :json => @standard.as_json(permissions: {user: @current_user}) }
format.json{ render :json => @standard.as_json(methods: [:display_name, :context_code, :assessed_assignment?, :context_name], permissions: {user: @current_user}) }
else
format.json{ render :json => @standard.errors, :status => :bad_request }
end
@ -61,12 +62,12 @@ class GradingStandardsController < ApplicationController
end
def update
@standard = @context.grading_standards.find(params[:id])
if authorized_action(@context, @current_user, :manage_grades)
@standard = GradingStandard.standards_for(@context).find(params[:id])
if authorized_action(@standard, @current_user, :manage)
@standard.user = @current_user
respond_to do |format|
if @standard.update_attributes(params[:grading_standard])
format.json{ render :json => @standard.as_json(permissions: {user: @current_user}) }
format.json{ render :json => @standard.as_json(methods: [:display_name, :context_code, :assessed_assignment?, :context_name], permissions: {user: @current_user}) }
else
format.json{ render :json => @standard.errors, :status => :bad_request }
end
@ -75,11 +76,11 @@ class GradingStandardsController < ApplicationController
end
def destroy
@standard = @context.grading_standards.find(params[:id])
if authorized_action(@context, @current_user, :manage_grades)
@standard = GradingStandard.standards_for(@context).find(params[:id])
if authorized_action(@standard, @current_user, :manage)
respond_to do |format|
if @standard.destroy
format.json{ render :json => @standard.as_json(permissions: {user: @current_user}) }
format.json{ render :json => @standard.as_json(methods: [:display_name, :context_code, :assessed_assignment?, :context_name], permissions: {user: @current_user}) }
else
format.json{ render :json => @standard.errors, :status => :bad_request }
end

View File

@ -0,0 +1,72 @@
/** @jsx React.DOM */
define([
'old_unsupported_dont_use_react',
'jsx/grading/gradingPeriod',
'jquery',
'i18n!external_tools',
'underscore',
'jquery.instructure_misc_plugins'
],
function(React, GradingPeriod, $, I18n, _) {
var GradingPeriodCollection = React.createClass({
getInitialState: function() {
return {periods: null};
},
componentWillMount: function() {
$.getJSON(ENV.GRADING_PERIODS_URL)
.done(this.gotPeriods)
},
gotPeriods: function(periods) {
this.setState({periods: periods.grading_periods});
},
deleteGradingPeriod: function(event, key) {
var self = this,
$period = $(event.target).parents(".grading-period");
$period.confirmDelete({
url: ENV.GRADING_PERIODS_URL + "/" + key,
message: I18n.t("Are you sure you want to delete this grading period?"),
success: function() {
$(this).slideUp(function() {
$(this).remove();
});
var newPeriods = _.reject(self.state.periods, function(period){ return period.id === key });
self.setState({periods: newPeriods});
},
error: function() {
$.flashError(I18n.t("There was a problem deleting the grading period"));
}
});
},
renderGradingPeriods: function() {
if(!this.state.periods){
return null;
} else if(this.state.periods.length === 0){
return <h3>{I18n.t("No grading periods to display")}</h3>;
}
var self = this;
return this.state.periods.map(function(period){
return (<GradingPeriod key={period.id} title={period.title} startDate={new Date(period.start_date)}
endDate={new Date(period.end_date)} weight={period.weight}
onDeleteGradingPeriod={self.deleteGradingPeriod}/>);
});
},
render: function () {
return(
<div id="grading_periods" className="content-box">
{this.renderGradingPeriods()}
</div>
);
}
});
return GradingPeriodCollection;
});

View File

@ -2,7 +2,7 @@
define([
'old_unsupported_dont_use_react',
'jsx/grading/data_row',
'jsx/grading/dataRow',
'jquery',
'i18n!external_tools'
],
@ -15,9 +15,7 @@ function(React, DataRow, $, I18n) {
standard: this.props.standard,
permissions: this.props.permissions,
editingStandard: $.extend(true, {}, this.props.standard),
editing: this.props.editing,
saving: false,
justAdded: this.props.justAdded
saving: false
};
},
@ -26,64 +24,37 @@ function(React, DataRow, $, I18n) {
standard: nextProps.standard,
permissions: nextProps.permissions,
editingStandard: $.extend(true, {}, this.props.standard),
editing: nextProps.editing,
saving: nextProps.saving,
justAdded: nextProps.justAdded
saving: nextProps.saving
});
},
componentDidMount: function() {
if(this.props.justAdded) this.refs.gradingStandardTitle.getDOMNode().focus();
},
componentDidUpdate: function(prevProps, prevState) {
if(this.state.editing !== prevState.editing) this.refs.gradingStandardTitle.getDOMNode().focus();
},
startEditing: function(event) {
event.preventDefault();
this.setState({editing: true});
},
stopEditing: function() {
if(this.state.justAdded){
return this.props.onDeleteGradingStandardNoWarning(this.props.key);
}else{
this.setState({standard: this.state.standard, editing: false,
editingStandard: $.extend(true, {}, this.state.standard)});
if(this.props.editing !== prevProps.editing){
this.refs.gradingStandardTitle.getDOMNode().focus();
this.setState({editingStandard: $.extend(true, {}, this.state.standard)})
}
},
triggerEditGradingStandard: function(event) {
event.preventDefault();
this.props.onSetEditingStatus(this.props.key, true);
},
triggerStopEditingGradingStandard: function() {
this.props.onSetEditingStatus(this.props.key, false);
},
triggerDeleteGradingStandard: function(event) {
return this.props.onDeleteGradingStandard(event, this.props.key);
},
dataFormattedForPost: function() {
var formattedData = { grading_standard: { title: this.state.editingStandard.title, standard_data: {} } };
for(i = 0; i < this.state.editingStandard.data.length; i++){
formattedData["grading_standard"]["standard_data"]["scheme_" + i] = {
name: this.state.editingStandard.data[i][0],
value: Math.round(this.state.editingStandard.data[i][1] * 10000)/100
};
};
return formattedData;
},
saveGradingStandard: function() {
var self = this;
var formattedData = this.dataFormattedForPost();
triggerSaveGradingStandard: function() {
this.setState({saving: true});
$.ajax({
type: "PUT",
url: ENV.GRADING_STANDARDS_URL + "/" + this.state.editingStandard.id,
data: formattedData,
dataType: "json"
})
.success(function(response){
self.setState({standard: response.grading_standard, editing: false,
editingStandard: $.extend(true, {}, response.grading_standard),
saving: false, justAdded: false});
})
.error(function(){
self.setState({saving: false});
$.flashError(I18n.t("There was a problem saving the grading scheme"));
});
return this.props.onSaveGradingStandard(this.state.editingStandard);
},
assessedAssignment: function() {
@ -96,9 +67,8 @@ function(React, DataRow, $, I18n) {
},
insertGradingStandardRow: function(index) {
var newEditingStandard = $.extend(true, {}, this.state.editingStandard);
newEditingStandard.data.splice(index + 1, 0, [""," "]);
this.setState({editingStandard: newEditingStandard});
this.state.editingStandard.data.splice(index + 1, 0, [""," "]);
this.setState({editingStandard: this.state.editingStandard});
},
titleChange: function(event) {
@ -117,6 +87,7 @@ function(React, DataRow, $, I18n) {
},
renderCannotManageMessage: function() {
if(this.props.permissions.manage && this.props.othersEditing) return null;
if(this.state.standard.context_name){
return (
<div>
@ -137,7 +108,7 @@ function(React, DataRow, $, I18n) {
},
renderTitle: function() {
if(this.state.editing){
if(this.props.editing){
return (
<div className="pull-left" tabIndex="0">
<input type="text" onChange={this.titleChange} className="grading_standard_title"
@ -157,10 +128,10 @@ function(React, DataRow, $, I18n) {
},
renderDataRows: function() {
var data = this.state.editing ? this.state.editingStandard.data : this.state.standard.data;
var data = this.props.editing ? this.state.editingStandard.data : this.state.standard.data;
return data.map(function(item, idx, array){
return (
<DataRow key={idx} row={item} siblingRow={array[idx - 1]} editing={this.state.editing}
<DataRow key={idx} row={item} siblingRow={array[idx - 1]} editing={this.props.editing}
onDeleteRow={this.deleteDataRow} onInsertRow={this.insertGradingStandardRow}
onRowMinScoreChange={this.changeRowMinScore} onRowNameChange={this.changeRowName}/>
);
@ -176,17 +147,17 @@ function(React, DataRow, $, I18n) {
);
}
return (
<button type="button" onClick={this.saveGradingStandard} className="btn btn-primary save_button">
<button type="button" onClick={this.triggerSaveGradingStandard} className="btn btn-primary save_button">
{I18n.t("Save")}
</button>
);
},
renderSaveAndCancelButtons: function() {
if(this.state.editing){
if(this.props.editing){
return (
<div className="form-actions">
<button type="button" onClick={this.stopEditing} className="btn cancel_button">
<button type="button" onClick={this.triggerStopEditingGradingStandard} className="btn cancel_button">
{I18n.t("Cancel")}
</button>
{this.renderSaveButton()}
@ -196,32 +167,34 @@ function(React, DataRow, $, I18n) {
return null;
},
renderEditIcon: function() {
if(!this.state.editing){
renderEditAndDeleteIcons: function() {
if(!this.props.editing){
return(
<a href="#" onClick={this.startEditing} title={I18n.t("Edit Grading Scheme")}
className={"edit_grading_standard_link no-hover " + (this.assessedAssignment() ? "read_only" : "")}
tabIndex="1">
<span className="screenreader-only">{I18n.t("Edit Grading Scheme")}</span>
<i className="icon-edit standalone-icon"/>
</a>
<div>
<a href="#" onClick={this.triggerEditGradingStandard} title={I18n.t("Edit Grading Scheme")}
className={"edit_grading_standard_link no-hover " + (this.assessedAssignment() ? "read_only" : "")}
tabIndex="1">
<span className="screenreader-only">{I18n.t("Edit Grading Scheme")}</span>
<i className="icon-edit standalone-icon"/>
</a>
<a href="#" title={I18n.t("Delete Grading Scheme")} onClick={this.triggerDeleteGradingStandard}
className="delete_grading_standard_link no-hover" tabIndex="1">
<span className="screenreader-only">{I18n.t("Delete Grading Scheme")}</span>
<i className="icon-trash standalone-icon"/>
</a>
</div>
);
}
return null;
},
renderIconsAndTitle: function() {
if(this.state.permissions.manage){
if(this.state.permissions.manage && !this.props.othersEditing){
return (
<div>
{this.renderTitle()}
<div className="links">
{this.renderEditIcon()}
<a href="#" title={I18n.t("Delete Grading Scheme")} onClick={this.triggerDeleteGradingStandard}
className="delete_grading_standard_link no-hover" tabIndex="1">
<span className="screenreader-only">{I18n.t("Delete Grading Scheme")}</span>
<i className="icon-trash standalone-icon"/>
</a>
{this.renderEditAndDeleteIcons()}
</div>
</div>
);

View File

@ -0,0 +1,172 @@
/** @jsx React.DOM */
define([
'old_unsupported_dont_use_react',
'jsx/grading/gradingStandard',
'jquery',
'i18n!external_tools',
'underscore',
'jquery.instructure_misc_plugins'
],
function(React, GradingStandard, $, I18n, _) {
var GradingStandardCollection = React.createClass({
getInitialState: function() {
return {standards: null};
},
componentWillMount: function() {
$.getJSON(ENV.GRADING_STANDARDS_URL)
.done(this.gotStandards)
},
gotStandards: function(standards) {
this.setState({standards: standards});
},
addGradingStandard: function() {
var newStandards = _.map(this.state.standards, function(standard){
standard.editing = false;
standard.justAdded = false;
return standard;
});
var newStandard = {
editing: true,
justAdded: true,
grading_standard: {
permissions: { manage: true },
title: "",
data: ENV.DEFAULT_DATA,
id: -1
}
};
newStandards.unshift(newStandard);
this.setState({standards: newStandards});
},
getStandardById: function(id) {
return _.find(this.state.standards, function(standard){ return standard.grading_standard.id === id });
},
standardNotCreated: function(gradingStandard){
return gradingStandard.id === -1;
},
setEditingStatus: function(id, setEditingStatusTo){
var existingStandard = this.getStandardById(id)
var indexToEdit = this.state.standards.indexOf(existingStandard);
if(setEditingStatusTo === false && this.standardNotCreated(existingStandard.grading_standard)){
var newStandards = this.state.standards;
newStandards.splice(indexToEdit, 1);
this.setState({standards: newStandards});
}else{
this.state.standards[indexToEdit].editing = setEditingStatusTo;
this.setState({standards: this.state.standards})
}
},
standardBeingEdited: function() {
return !!_.find(this.state.standards, function(standard){return standard.editing});
},
saveGradingStandard: function(standard) {
var indexToUpdate = this.state.standards.indexOf(this.getStandardById(standard.id));
if(standard.title === "" && this.standardNotCreated(standard)) standard.title = "New Grading Scheme";
var self = this;
$.ajax({
type: this.standardNotCreated(standard) ? "POST" : "PUT",
url: this.standardNotCreated(standard) ? ENV.GRADING_STANDARDS_URL : ENV.GRADING_STANDARDS_URL + "/" + standard.id,
data: this.dataFormattedForUpdate(standard),
dataType: "json"
})
.success(function(updatedStandard){
self.state.standards[indexToUpdate] = updatedStandard;
self.setState({standards: self.state.standards});
})
.error(function(){
self.state.standards[indexToUpdate].grading_standard.saving = false;
self.setState({standards: self.state.standards});
$.flashError(I18n.t("There was a problem saving the grading scheme"));
});
},
dataFormattedForUpdate: function(standard) {
var formattedData = { grading_standard: { title: standard.title, standard_data: {} } };
for(i = 0; i < standard.data.length; i++){
formattedData["grading_standard"]["standard_data"]["scheme_" + i] = {
name: standard.data[i][0],
value: Math.round(standard.data[i][1] * 10000)/100
};
};
return formattedData;
},
deleteGradingStandard: function(event, key) {
var self = this,
$standard = $(event.target).parents(".grading_standard");
$standard.confirmDelete({
url: ENV.GRADING_STANDARDS_URL + "/" + key,
message: I18n.t("Are you sure you want to delete this grading scheme?"),
success: function() {
$(this).slideUp(function() {
$(this).remove();
});
var newStandards = _.reject(self.state.standards, function(standard){ return standard.grading_standard.id === key });
self.setState({standards: newStandards});
},
error: function() {
$.flashError(I18n.t("There was a problem deleting the grading scheme"));
}
});
},
hasAdminOrTeacherRole: function() {
return _.intersection(ENV.current_user_roles, ["teacher", "admin"]).length > 0;
},
getAddButtonCssClasses: function() {
var classes = "btn pull-right add_standard_link"
if(!this.hasAdminOrTeacherRole() || this.standardBeingEdited()) classes += " disabled"
return classes;
},
renderGradingStandards: function() {
if(!this.state.standards){
return null;
} else if(this.state.standards.length === 0){
return <h3>{I18n.t("No grading schemes to display")}</h3>;
}
var self = this;
return this.state.standards.map(function(s){
return (<GradingStandard key={s.grading_standard.id} standard={s.grading_standard}
editing={!!s.editing} permissions={s.grading_standard.permissions}
justAdded={s.justAdded} onSetEditingStatus={self.setEditingStatus}
othersEditing={!s.editing && self.standardBeingEdited()}
onDeleteGradingStandard={self.deleteGradingStandard}
onSaveGradingStandard={self.saveGradingStandard}/>);
});
},
render: function () {
return(
<div>
<div className="rs-margin-all pull-right">
<a href="#" onClick={this.addGradingStandard} className={this.getAddButtonCssClasses()}>
<i className="icon-add"/>
{I18n.t(" Add grading scheme")}
</a>
</div>
<div id="standards" className="content-box react_grading_standards">
{this.renderGradingStandards()}
</div>
</div>
);
}
});
return GradingStandardCollection;
});

View File

@ -0,0 +1,51 @@
/** @jsx React.DOM */
define([
'old_unsupported_dont_use_react',
'jsx/grading/gradingStandardCollection',
'jsx/grading/gradingPeriodCollection',
'jquery',
'i18n!external_tools',
'underscore',
'jquery.instructure_misc_plugins'
],
function(React, GradingStandardCollection, GradingPeriodCollection, $, I18n, _) {
var TabContainer = React.createClass({
componentDidMount: function() {
$(this.getDOMNode()).children(".ui-tabs-minimal").tabs();
},
render: function () {
if(ENV.MULTIPLE_GRADING_PERIODS){
return (
<div>
<div className="ui-tabs-minimal">
<ul>
<li><a href="#grading-periods-tab" className="grading_periods_tab"> {I18n.t('Grading Periods')}</a></li>
<li><a href="#grading-standards-tab" className="grading_standards_tab"> {I18n.t('Grading Schemes')}</a></li>
</ul>
<div id="grading-periods-tab">
<GradingPeriodCollection/>
</div>
<div id="grading-standards-tab">
<GradingStandardCollection/>
</div>
</div>
</div>
);
} else{
return (
<div>
<h1 tabIndex="0">{I18n.t("Grading Schemes")}</h1>
<GradingStandardCollection/>
</div>
);
}
}
});
React.renderComponent(<TabContainer/>, document.getElementById("react_grading_tabs"));
});

View File

@ -1,209 +0,0 @@
/** @jsx React.DOM */
define([
'old_unsupported_dont_use_react',
'jsx/grading/grading_standard',
'jsx/grading/grading_period',
'jquery',
'i18n!external_tools',
'underscore',
'jquery.instructure_misc_plugins'
],
function(React, GradingStandard, GradingPeriod, $, I18n, _) {
var TabContainer = React.createClass({
getInitialState: function() {
return {standards: null, periods: null};
},
componentWillMount: function() {
$.getJSON(ENV.GRADING_STANDARDS_URL)
.done(this.gotStandards)
if(ENV.MULTIPLE_GRADING_PERIODS){
$.getJSON(ENV.GRADING_PERIODS_URL)
.done(this.gotPeriods)
}
},
gotStandards: function(standards) {
this.setState({standards: standards});
},
gotPeriods: function(periods) {
this.setState({periods: periods.grading_periods});
},
componentDidMount: function() {
$(this.getDOMNode()).children(".ui-tabs-minimal").tabs();
},
addGradingStandard: function() {
var newStandards = _.map(this.state.standards, function(standard){
standard.editing = false;
standard.justAdded = false;
return standard;
});
var self = this;
$.ajax({
type: "POST",
url: ENV.GRADING_STANDARDS_URL,
data: { grading_standard: { title: I18n.t("New Title") } },
dataType: "json"
})
.success(function(newStandard) {
newStandard.editing = true;
newStandard.justAdded = true;
newStandards.unshift(newStandard);
$(this).slideDown();
self.setState({standards: newStandards});
})
.error(function() {
$.flashError(I18n.t("There was a problem adding the grading scheme"));
});
},
deleteGradingStandard: function(event, key) {
var self = this,
$standard = $(event.target).parents(".grading_standard");
$standard.confirmDelete({
url: ENV.GRADING_STANDARDS_URL + "/" + key,
message: I18n.t("Are you sure you want to delete this grading scheme?"),
success: function() {
$(this).slideUp(function() {
$(this).remove();
});
var newStandards = _.reject(self.state.standards, function(standard){ return standard.grading_standard.id === key });
self.setState({standards: newStandards});
},
error: function() {
$.flashError(I18n.t("There was a problem deleting the grading scheme"));
}
});
},
deleteGradingPeriod: function(event, key) {
var self = this,
$period = $(event.target).parents(".grading-period");
$period.confirmDelete({
url: ENV.GRADING_PERIODS_URL + "/" + key,
message: I18n.t("Are you sure you want to delete this grading period?"),
success: function() {
$(this).slideUp(function() {
$(this).remove();
});
var newPeriods = _.reject(self.state.periods, function(period){ return period.id === key });
self.setState({periods: newPeriods});
},
error: function() {
$.flashError(I18n.t("There was a problem deleting the grading period"));
}
});
},
deleteGradingStandardNoWarning: function(key) {
var self = this;
$.ajax({
type: "DELETE",
url: ENV.GRADING_STANDARDS_URL + "/" + key,
dataType: "json"
})
.success(function(){
var newStandards = _.reject(self.state.standards, function(standard){ return standard.grading_standard.id === key });
self.setState({standards: newStandards});
})
.error(function(){
$.flashError(I18n.t("There was a problem deleting the grading scheme"));
});
},
hasAdminOrTeacherRole: function() {
return _.intersection(ENV.current_user_roles, ["teacher", "admin"]).length > 0;
},
renderAddGradingStandardButton: function() {
if(this.hasAdminOrTeacherRole()){
return(
<div className="rs-margin-all pull-right">
<a href="#" onClick={this.addGradingStandard} className="btn pull-right add_standard_link">
<i className="icon-add"/>
{I18n.t(" Add grading scheme")}
</a>
</div>
);
}
return null;
},
renderGradingStandards: function() {
if(!this.state.standards){
return null;
} else if(this.state.standards.length === 0){
return <h3>{I18n.t("No grading schemes to display")}</h3>;
}
var self = this;
return this.state.standards.map(function(s){
return (<GradingStandard key={s.grading_standard.id} standard={s.grading_standard}
editing={!!s.editing} permissions={s.grading_standard.permissions}
justAdded={!!s.justAdded} onDeleteGradingStandard={self.deleteGradingStandard}
onDeleteGradingStandardNoWarning={self.deleteGradingStandardNoWarning}/>);
});
},
renderGradingPeriods: function() {
if(!this.state.periods){
return null;
} else if(this.state.periods.length === 0){
return <h3>{I18n.t("No grading periods to display")}</h3>;
}
var self = this;
return this.state.periods.map(function(p){
return (<GradingPeriod key={p.id} title={p.title} startDate={new Date(p.start_date)}
endDate={new Date(p.end_date)} weight={p.weight}
onDeleteGradingPeriod={self.deleteGradingPeriod}/>);
});
},
render: function () {
if(ENV.MULTIPLE_GRADING_PERIODS){
return (
<div>
<div className="ui-tabs-minimal">
<ul>
<li><a href="#grading-periods-tab" className="grading_periods_tab"> {I18n.t('Grading Periods')}</a></li>
<li><a href="#grading-standards-tab" className="grading_standards_tab"> {I18n.t('Grading Schemes')}</a></li>
</ul>
<div id="grading-periods-tab">
<div id="grading_periods" className="content-box">
{this.renderGradingPeriods()}
</div>
</div>
<div id="grading-standards-tab">
{this.renderAddGradingStandardButton()}
<div id="standards" className="content-box react_grading_standards">
{this.renderGradingStandards()}
</div>
</div>
</div>
</div>
);
} else{
return (
<div>
<h1 tabIndex="0">{I18n.t("Grading Schemes")}</h1>
{this.renderAddGradingStandardButton()}
<div id="standards" className="content-box react_grading_standards">
{this.renderGradingStandards()}
</div>
</div>
);
}
}
});
React.renderComponent(<TabContainer/>, document.getElementById("react_grading_tabs"));
});

View File

@ -17,6 +17,17 @@ describe "grading standards" do
should_delete_a_grading_scheme(@course, "/courses/#{@course.id}/grading_standards")
end
it "should display correct info when multiple standards are added without refreshing page" do
course_with_teacher_logged_in
get "/courses/#{@course.id}/grading_standards"
should_add_a_grading_scheme(name: "First Grading Standard")
first_grading_standard = @new_grading_standard
should_add_a_grading_scheme(name: "Second Grading Standard")
second_grading_standard = @new_grading_standard
expect(fj("#grading_standard_#{first_grading_standard.id} span:eq(1)").text).to eq("First Grading Standard")
expect(fj("#grading_standard_#{second_grading_standard.id} span:eq(1)").text).to eq("Second Grading Standard")
end
it "should allow setting a grading standard for an assignment" do
course_with_teacher_logged_in

View File

@ -14,15 +14,15 @@ def simple_grading_standard(context)
})
end
def should_add_a_grading_scheme
new_standard_name = 'new grading standard'
def should_add_a_grading_scheme(options = {name: "new grading standard"})
new_standard_name = options[:name]
f('.add_standard_link').click
replace_content(f('.scheme_name'), new_standard_name)
f('.save_button').click
wait_for_ajax_requests
new_grading_standard = GradingStandard.last
expect(new_grading_standard.title).to eq new_standard_name
expect(f("#grading_standard_#{new_grading_standard.id}")).to be_displayed
@new_grading_standard = GradingStandard.last
expect(@new_grading_standard.title).to eq new_standard_name
expect(f("#grading_standard_#{@new_grading_standard.id}")).to be_displayed
end
def should_edit_a_grading_scheme(context, url)