Skip to content

Commit

Permalink
SAK-32769 Improve scalability and performance of the GradebookNG table (
Browse files Browse the repository at this point in the history
sakaiproject#4685)

* SAK-32769 Replace the GradebookNG Wicket DataTable with a progressively rendered table to improve scaling and performance issues

* SAK-32769 fix the save green bg color not showing

* SAK-32769 fix caption in handsontable causing rendering issues in firefox

* SAK-32769 allow the toolbar buttons to wrap and still be clicky

* SAK-32769 round up when .5

* SAK-32769 jump to the assignment column after creation/edit

* SAK-32769 rearrange the toolbar actions

* SAK-32769 tinker the student column and filter styles

* SAK-32769 improve container offsets so scrollbar is visible and clickable

* SAK-32769 allow student cell content to wrap

* SAK-32769 flash green when updating the course grade or category average

* SAK-32769 align cell values in center of cell when student names cause row to be taller than 30px

* SAK-32769 fix alignment of comments icon and word-breaks for student names in firefox

* SAK-32769 fix js error when scrolling past col 15 due to attempted replacement of the student column

* SAK-32769 set autoRowSize to true and ensure header cache clones dom elements to avoid stealing elements from other instances of the some header

* SAK-32769 ensure oldScore of '' is respected

* SAK-32769 replace currentRow and currentCol bg colors with a border-top/border-bottom on the currentRow only

* SAK-32769 add padding around the add gradebook item

* SAK-32769 don't delete the GbGradeTable.lastValidGrades[studentId] out from under a concurrent ajax request

* SAK-32769 Reduce rounding errors when displaying category totals

* SAK-32769 fix fixed grade column width

* SAK-32769 Deal with a null value in the student cell render

* SAK-32769 force fixed row height and put student name on two rows so name and eid is always visible (even if clipped)

* SAK-32769 reduce space around the add gradebook row

* SAK-32769 category average column should be readOnly

* SAK-32769 adjust handsontable z-index so the fixed header doesn't interfere with the site menu dropdowns

* SAK-32769 Temp commit to look into why drop lowest restriction isn't firing.

* SAK-32769 Remove debugging + switch Long comparisons to use .equals

* SAK-32769 add zebra striping to table, lighten category ave bg color, and remove bg color from student and grade columns

* SAK-32769 fix 'x' undefined in conflict notification

* SAK-32769 only allow column filter label to get to ~140px

* SAK-32769 show abbreviated version of title in assignment column headers

* SAK-32769 give course grade and student column left/right padding, clip student cell text if overflow and lighten header cell text color

* SAK-32769 increase metadata popover font size

* SAK-32769 put category weight and label on new line

* SAK-32769 Reduce 'Category' text in GB Item column headers

* SAK-32769 show overridden course grades as bold

* SAK-32769 fix ec bg color not displaying on shaded rows

* SAK-32769 fix sort state not sticking and also not sorting accurately

* SAK-32769 Improve performance on Firefox:

  * Cache parsed HTML fragments to avoid lots of parsing

  * Don't update style elements if we're not changing their values

  * Don't display the ghostly table header

* SAK-32769 fix deserialisation error hit on MoveAssignmentLeftAction by removing the business service from the action class constructors

* SAK-32769 refactor ActionImpl to InjectableAction.. wooooooo

* SAK-32769 ensure invalid doubles are treated as errors

* SAK-32769 fix default sort state and ensure sort state changes as the sort order changes

* SAK-32769 dismiss any feedback messages upon setting a score value

* SAK-32769 add a clear action to the student filter input

* SAK-32769 fix NPE in import process

* SAK-32769 only have two sort states desc and asc (remove the weird 'null' state)

* SAK-32769 allow filter dropdown menu items to wrap

* SAK-32769 update the grade item title validation rules to only check for # at beginning of the string

* SAK-32769 disable the continue button until an import file has been selected

* SAK-32769 fix icon prefix for 11.x and default icon to fa-globe if cannot map external app

* SAK-32769 Implement decimal helpers to handle locale for incoming decimal values with a float.  Also ensure the locale is used when displaying a decimal value to the user.

* SAK-32769 Squash into 49c0540

* SAK-32769 First pass code review -- add final to final attributes, remove fixme  and clarify `this` calls

* SAK-32769 Fix typo in gbgrades js

* SAK-32769 Fix viewing grade summary not clearing selection so keyboard cannot interact with dialog

* SAK-32769 Fix positionModalAtTop throwing a js error

* SAK-32769 Fix GradeUpdateResponse not including whether course grade was an override so lost bold on course grade column cell

* SAK-32769 fix required CSS not adding to Wicket labels and show asterisk on those required fields

* SAK-32769 don't allow TA's to see unreleased course grade via student grade summary panel

* SAK-32769 hide edit settings link from TAs in tooltip grade release tooltip

* SAK-32769 TA should be able to view all course grade elements if they have been granted permission (regardless of whether the course grade is released to students)

* SAK-32769 ensure TA without course grade permission doesn't see course grade after setting a score

* SAK-32769 ensure TA permissions are checked when setting up the course grade formatter for the grade summary panel

* SAK-32769 only show the unreleased warning on the grade summary to the TA if they have access to view the course grades

* SAK-32737 - Decimal separator issues in categories & weighting (sakaiproject#4645)

* SAK-32751 when uncatagorised, ensure that when assignment  is true in the database always show this as uncounted in the UI, as it is not counted until assigned to a category (this matches the gradebook classic behaviour)

* SAK-32769 increase out-of font-size

* SAK-32769 add hide action to assignment and category column menus

* SAK-32769 Remove FIXME

* SAK-32769 Use jackson to generate our JSON

* SAK-32769 Remove stray FIXME

* SAK-32769 Reformat code using eclipse

* SAK-32769 refactor GbGradebookData to take the GbGradeTableData rather than overloading the constructor

* SAK-32608 Port student number customisations to the new progressive render GradebookNG table

* SAK-32608 Deal with the fact that CandidateDetailProvider might not be present.

* SAK-32608 remove unused student number java panels
  • Loading branch information
payten authored and ottenhoff committed Aug 18, 2017
1 parent fada42c commit ecca29b
Show file tree
Hide file tree
Showing 130 changed files with 8,023 additions and 7,252 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.sakaiproject.service.gradebook.shared;

import org.apache.commons.lang3.StringUtils;

public class GradebookHelper {

/**
* Validate a grade item title by checking against the reserved characters
* @param title
* @throws InvalidGradeItemNameException
*/
public static void validateGradeItemName(final String title) throws InvalidGradeItemNameException {
if (StringUtils.isBlank(title)
|| StringUtils.containsAny(title, GradebookService.INVALID_CHARS_IN_GB_ITEM_NAME)
|| StringUtils.startsWithAny(title, GradebookService.INVALID_CHARS_AT_START_OF_GB_ITEM_NAME)) {
throw new InvalidGradeItemNameException("Grade Item name is invalid: " + title);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ public enum PointsPossibleValidation {
/**
* Array of chars that are not allowed in a gb item title
*/
public static final char[] INVALID_CHARS_IN_GB_ITEM_NAME = {'*', '#', '[', ']'};
public static final char[] INVALID_CHARS_IN_GB_ITEM_NAME = {'*', '[', ']'};
public static final String[] INVALID_CHARS_AT_START_OF_GB_ITEM_NAME = {"#"};

/**
* Comparator to ensure correct ordering of letter grades, catering for + and - in the grade
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/***********************************************************************************
*
* Copyright (c) 2007, 2008 The Sakai Foundation, The MIT Corporation
*
* Licensed under the Educational Community License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.opensource.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
**********************************************************************************/

package org.sakaiproject.service.gradebook.shared;

public class InvalidGradeItemNameException extends GradebookException {

private static final long serialVersionUID = 1L;

public InvalidGradeItemNameException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
import org.sakaiproject.service.gradebook.shared.ConflictingAssignmentNameException;
import org.sakaiproject.service.gradebook.shared.ConflictingCategoryNameException;
import org.sakaiproject.service.gradebook.shared.GradebookExternalAssessmentService;
import org.sakaiproject.service.gradebook.shared.GradebookHelper;
import org.sakaiproject.service.gradebook.shared.GradebookNotFoundException;
import org.sakaiproject.service.gradebook.shared.GradebookService;
import org.sakaiproject.service.gradebook.shared.GraderPermission;
Expand Down Expand Up @@ -283,11 +284,8 @@ private Assignment prepareNewAssignment(String name, Double points, Date dueDate
}

// name cannot contain these special chars as they are reserved for special columns in import/export
if(StringUtils.containsAny(validatedName, GradebookService.INVALID_CHARS_IN_GB_ITEM_NAME)) {
// TODO InvalidAssignmentNameException plus move all exceptions to their own package
throw new ConflictingAssignmentNameException("Assignment names cannot contain *, #, [ or ] as they are reserved");
}

GradebookHelper.validateGradeItemName(validatedName);

Assignment asn = new Assignment();
asn.setName(validatedName);
asn.setPointsPossible(points);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
import org.sakaiproject.service.gradebook.shared.ExternalAssignmentProvider;
import org.sakaiproject.service.gradebook.shared.ExternalAssignmentProviderCompat;
import org.sakaiproject.service.gradebook.shared.GradebookExternalAssessmentService;
import org.sakaiproject.service.gradebook.shared.GradebookHelper;
import org.sakaiproject.service.gradebook.shared.GradebookNotFoundException;
import org.sakaiproject.service.gradebook.shared.GradebookService;
import org.sakaiproject.service.gradebook.shared.InvalidCategoryException;
Expand Down Expand Up @@ -173,10 +174,7 @@ public synchronized void addExternalAssessment(final String gradebookUid, final
}

// name cannot contain these chars as they are reserved for special columns in import/export
if(StringUtils.containsAny(title, GradebookService.INVALID_CHARS_IN_GB_ITEM_NAME)) {
// TODO InvalidAssignmentNameException plus move all exceptions to their own package
throw new ConflictingAssignmentNameException("Assignment names cannot contain *, #, [ or ] as they are reserved");
}
GradebookHelper.validateGradeItemName(title);

getHibernateTemplate().execute(session -> {
// Ensure that the externalId is unique within this gradebook
Expand Down Expand Up @@ -235,10 +233,7 @@ public void updateExternalAssessment(final String gradebookUid, final String ext
}

// name cannot contain these chars as they are reserved for special columns in import/export
if(StringUtils.containsAny(title, GradebookService.INVALID_CHARS_IN_GB_ITEM_NAME)) {
// TODO InvalidAssignmentNameException plus move all exceptions to their own package
throw new ConflictingAssignmentNameException("Assignment names cannot contain *, #, [ or ] as they are reserved");
}
GradebookHelper.validateGradeItemName(title);

HibernateCallback<?> hc = new HibernateCallback<Object>() {
@Override
Expand Down Expand Up @@ -717,10 +712,7 @@ public synchronized void addExternalAssessment(final String gradebookUid, final
}

// name cannot contain these chars as they are reserved for special columns in import/export
if(StringUtils.containsAny(title, GradebookService.INVALID_CHARS_IN_GB_ITEM_NAME)) {
// TODO InvalidAssignmentNameException plus move all exceptions to their own package
throw new ConflictingAssignmentNameException("Assignment names cannot contain *, #, [ or ] as they are reserved");
}
GradebookHelper.validateGradeItemName(title);

getHibernateTemplate().execute(session -> {
// Ensure that the externalId is unique within this gradebook
Expand Down Expand Up @@ -794,10 +786,7 @@ public void updateExternalAssessment(final String gradebookUid, final String ext
}

// name cannot contain these chars as they are reserved for special columns in import/export
if(StringUtils.containsAny(title, GradebookService.INVALID_CHARS_IN_GB_ITEM_NAME)) {
// TODO InvalidAssignmentNameException plus move all exceptions to their own package
throw new ConflictingAssignmentNameException("Assignment names cannot contain *, #, [ or ] as they are reserved");
}
GradebookHelper.validateGradeItemName(title);

HibernateCallback<?> hc = session -> {
asn.setExternalInstructorLink(externalUrl);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
import org.sakaiproject.service.gradebook.shared.ConflictingCategoryNameException;
import org.sakaiproject.service.gradebook.shared.GradeDefinition;
import org.sakaiproject.service.gradebook.shared.GradeMappingDefinition;
import org.sakaiproject.service.gradebook.shared.GradebookHelper;
import org.sakaiproject.service.gradebook.shared.GradebookInformation;
import org.sakaiproject.service.gradebook.shared.GradebookNotFoundException;
import org.sakaiproject.service.gradebook.shared.GradebookPermissionService;
Expand Down Expand Up @@ -805,10 +806,7 @@ public void updateAssignment(final String gradebookUid, final Long assignmentId,
}

// name cannot contain these chars as they are reserved for special columns in import/export
if(StringUtils.containsAny(validatedName, GradebookService.INVALID_CHARS_IN_GB_ITEM_NAME)) {
// TODO InvalidAssignmentNameException plus move all exceptions to their own package
throw new ConflictingAssignmentNameException("Assignment names cannot contain *, #, [ or ] as they are reserved");
}
GradebookHelper.validateGradeItemName(validatedName);

final Gradebook gradebook = this.getGradebook(gradebookUid);

Expand Down
10 changes: 10 additions & 0 deletions gradebookng/tool/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,16 @@
<groupId>org.apache.commons</groupId>
<artifactId>commons-math3</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<resources>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

import org.apache.wicket.core.request.handler.PageProvider;
import org.apache.wicket.core.request.handler.RenderPageRequestHandler;
import org.apache.wicket.RuntimeConfigurationType;
import org.apache.wicket.Application;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.session.ISessionStore;
import org.apache.wicket.request.IRequestHandler;
import org.apache.wicket.request.cycle.AbstractRequestCycleListener;
import org.apache.wicket.request.cycle.RequestCycle;
Expand Down Expand Up @@ -61,6 +64,8 @@ public void init() {
// for production, set to SHOW_NO_EXCEPTION_PAGE
getExceptionSettings().setUnexpectedExceptionDisplay(IExceptionSettings.SHOW_EXCEPTION_PAGE);

final ISessionStore sessionStore = getSessionStore();

// Intercept any unexpected error stacktrace and take to our page
getRequestCycleListeners().add(new AbstractRequestCycleListener() {
@Override
Expand All @@ -70,7 +75,7 @@ public IRequestHandler onException(final RequestCycle cycle, final Exception e)
});

// Disable Wicket's loading of jQuery - we load Sakai's preferred version in BasePage.java
getJavaScriptLibrarySettings().setJQueryReference(new PackageResourceReference(GradebookNgApplication.class,"empty.js"));
getJavaScriptLibrarySettings().setJQueryReference(new PackageResourceReference(GradebookNgApplication.class, "empty.js"));

// cleanup the HTML
getMarkupSettings().setStripWicketTags(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ label.avg=Avg:
label.total=Total:
label.relativeweight=Relative weight:
label.due=Due:
label.category=Cat:
label.noduedate=-
label.percentage.valued={0}%
label.percentage.plain=%
Expand All @@ -41,14 +42,18 @@ label.gradeitem.counted=Gradebook Item is included in the course grade calculati
label.gradeitem.notcounted=Gradebook Item not included in course grade calculation.
label.gradeitem.extracredit=This is an Extra Credit Gradebook Item
label.gradeitem.extracreditcategory=This is an Extra Credit Category
label.gradeitem.categoryaverage=Category Average for {0}
label.gradeitem.categoryaverage={0} Weighted Average
label.gradeitem.categoryaveragelabel=Weighted Average
label.gradeitem.categoryheadertooltip=Category: {0}
label.gradeitem.categoryweight=Category weight
label.gradeitem.categoryandweightheadertooltip=Category: {0}, Weight: {1}
label.toolbar.gradeitemsummary=Showing <span class='gb-item-summary-counts'><span class='visible'>{0}</span> of <span class='total'>{1}</span> items</span>
label.toolbar.toggleitems=View Columns
label.toolbar.togglecategories=Group By Category
label.toolbar.sortgradeitems=Item Order
label.toolbar.gradeitemsummary=Showing <span class='gb-item-summary-counts'><span class='visible'>{0}</span> of <span class='total'>{1}</span></span> columns
label.toolbar.gradeitemsummary-tooltip=Showing {0} of {1} columns ({2} of {3} items, {4} of {5} category averages)
label.toolbar.studentsummarypaginated=Showing {0} to {1} of {2} students
label.toolbar.studentsummary=Showing <span class='gb-student-summary-counts'><span class="visible">{0}</span></span> students
table.toolbar.categorytoggle=Group By Category
label.toolbar.gradeitemstoggle=Show/Hide Items
label.toolbar.gradeitemshowall=Show All
label.toolbar.gradeitemhideall=Hide All
label.toolbar.gradeitemshowthiscategory=Show this category
Expand All @@ -64,6 +69,7 @@ label.toolbar.gradeitemhidethiscategoryscore=Hide this column
label.toolbar.categorygroup.menulabel=Open menu for this category column
label.toolbar.gradeitem.menulabel=Open menu for this Gradebook Item column
label.toolbar.categoryaverage.menulabel=Open menu for this category score column
label.toolbar.togglehelp=Toggle grade table and keyboard navigation help

label.concurrentuserwarning=Please be aware a colleague has just made some changes to this Gradebook.<br>Refresh your page often to ensure you have the latest values.
error.concurrentedit=Concurrent edits have been detected. Refresh the tool to see the latest scores.
Expand All @@ -74,6 +80,7 @@ column.header.studentNumber = Student Number
column.header.coursegrade = Course Grade

filter.students = Filter students
filter.studentsclear = Clear student filter
filter.groups = Filter by group/section

button.addgradeitem = Add Gradebook Item
Expand Down Expand Up @@ -290,7 +297,15 @@ message.addcoursegradeoverride.invalid = The course grade entered is invalid acc

message.updateungradeditems.success=The ungraded items were updated.

gradespage.caption = Rows of student names. Columns of gradebook items. Press enter key in a cell to add or edit a grade. Two tabs to move through each cell. Filter list with accesskey F.
gradetable.wrapper.tooltip = This is the wrapper of the grades table data. Hit 'return' to enter the table data and 'escape' to return to this point.
gradetable.caption.summaryheader = Table Summary
gradetable.caption.summary = Rows of students. First column is student name. Second column is course grade. Other columns are gradebook items and category averages (if enabled). Press enter key in a cell to add or edit a grade. Filter list with accesskey F.
gradetable.caption.keyboardnavigationheader = Keyboard Navigation
gradetable.caption.keyboardnavigation = <p>Use the access key 'g' skip to the grades table and hit 'return' to enter table mode and begin navigating the grades data. Once in table mode, the tab key and arrow keys allow you to navigate the table cells. To edit a grade, hit the 'return' key or begin entering the student's score. When editing a score, hit 'escape' to cancel your changes and 'return' to save your changes. When you have finished, hit 'escape' to exit table mode.<p>
gradetable.caption.keyboardshortcutsheader = Keyboard Shortcuts
gradetable.caption.keyboardshortcuts = <p>Accesskey shortcuts (note: your AccessKeyShortcut this will depend on your browser and operating system - <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/accesskey" target="_blank" tabindex="-1">more information</a>)</p><dl class="dl-horizontal"><dt>Jump to the Grades Table</dt><dd>AccessKeyShortcut + g</dd><dt>Jump to Student Filter</dt><dd>AccessKeyShortcut + f</dd></dl><p>When the grades table is focused:</p><dl class="dl-horizontal"><dt>Enter table mode</dt><dd>Return</dd></dl>
gradetable.caption.keyboardtablemodeshortcuts = <p>When in table mode:</p><dl class="dl-horizontal"><dt>Navigate cells</dt><dd>Arrow keys or Tab</dd><dt>Open cell menu</dt><dd>Space</dd><dt>Open cell header menu</dt><dd>Control + Space</dd><dt>Toggle cell summary</dt><dd>s</dd><dt>Exit table mode</dt><dd>ESC</dd></dl>
gradetable.caption.keyboardeditingshortcuts = <p>When editing a score:</p><dl class="dl-horizontal"><dt>Cancel changes</dt><dd>ESC</dd><dt>Save changes</dt><dd>Return</dd></dl>

grade.option.viewlog = Grade Log
grade.log.entry = {0} - Score set to <b>{1}</b> by {2}
Expand All @@ -299,13 +314,17 @@ grade.outof = /{0}
grade.menulabel = Open menu for student {0} and assignment {1} cell

grade.notifications.hascomment = Gradebook item has comments
grade.notifications.commentloading = Loading comment...
grade.notifications.editcomment = Edit Comment
grade.notifications.haserror = An error occurred saving this item score.
grade.notifications.overlimit = Score is over item's maximum point value and is providing extra credit.
grade.notifications.concurrentedit = A concurrent edit has been detected. Please refresh the tool to view the latest scores.
grade.notifications.concurrenteditbyuser = <span class="gb-concurrent-edit-user">{0}</span> edited this score at <span class="gb-concurrent-edit-time">{1}</span>. Please refresh the tool to view the latest scores.
grade.notifications.isexternal = Gradebook item has been imported from an external tool and can only be edited from within that tool.
grade.notifications.concurrentedituser = Edited by:
grade.notifications.concurrentedittime = At time:
grade.notifications.isexternal = Go to {0} tool to edit scores for this item.
grade.notifications.invalid = Item score must be a positive number/decimal with a maximum of 10 integers and 2 decimal places.
grade.notifications.readonly = Insufficient privileges to edit this Gradebook item score
grade.notifications.readonly = Item score is read only
grade.notifications.privileges = Insufficient privileges to edit this Gradebook item score
grade.notifications.revert = Revert to Previous Score
grade.notifications.saved = All changes saved.
grade.notifications.error = Errors were detected. See cell notifications below.
Expand Down Expand Up @@ -481,11 +500,11 @@ column.header.coursegradeoverride.gradeoverride = Grade Override
coursegrade.display.percentage-first = {0}
coursegrade.display.percentage-second = ({0})
coursegrade.display.points-first = {0}/{1}
coursegrade.display.points-second = <br>[{0}/{1}]
coursegrade.display.points-second = [{0}/{1}]
coursegrade.display.points-none = -
coursegrade.display.none = -
coursegrade.option.showpoints = Show Points
coursegrade.option.hidepoints = Hide points
coursegrade.option.hidepoints = Hide Points

link.coursegradeoverride.revert.tooltip = Removes the course grade override and reverts to the calculated course grade
link.coursegradeoverride.reverttocalculated = Revert to calculated course grade
Expand All @@ -494,12 +513,13 @@ feedback.saving = Saving...
feedback.saved = All changes saved.
feedback.error = Errors were detected. See cell notifications below.
feedback.connectiontimeout = Unable to connect. Changes cannot be saved while offline.
feedback.reordercolumnsfailed = An error occurred while reordering columns.

ta.nopermission = You do not have permission to view the gradebook. Please contact your instructor.
ta.roleswapped = TA view of gradebook cannot be displayed.

error.addeditgradeitem.categorypoints = This gradebook item is configured with a category that has drop highest/drop lowest/keep highest enabled. The points for this gradebook item must match the current maximum of {0}.
error.addeditgradeitem.titlecharacters = Gradebook item names cannot contain *, #, [ or ] as they are reserved.
error.addeditgradeitem.titlecharacters = Gradebook item names cannot contain characters '*', '[', ']' or start with a '#' as they are reserved.

importExport.error.grade = An error occurred importing a grade. Please check the file.
importExport.error.comment = An error occurred importing a comment. Please check the file.
Expand All @@ -519,3 +539,23 @@ error.role=Your role in this site is improperly configured. You must have one of

ta.null=Select a grader

sortgradeitems.heading=Sort Grade Items
sortgradeitems.bycategory=By Category
sortgradeitems.bygradeitem=By Grade Item
sortgradeitems.submit=Update Sort Order
sortgradeitems.submitbycategory=Update Categorized Sort Order
sortgradeitems.success.byitem=Sort Order Updated
sortgradeitems.success.bycategory=Categorized Sort Order Updated
sortgradeitems.error=Unable to update sort order. Please contact your System Administrator.

metadata.header=Current Cell Metadata
metadata.student=Student:
metadata.assignment=Assignment:
metadata.score=Score:
metadata.courseGrade=Course Grade:
metadata.category=Category:
metadata.categoryAverage=Category Average:
metadata.flags=This score has the following flags:
metadata.noflags=No notifications

AutoLabel.CSS.required=required
Loading

0 comments on commit ecca29b

Please sign in to comment.