diff --git a/src/components/Gradebook/index.jsx b/src/components/Gradebook/index.jsx
index 607df3e..1c48b0f 100644
--- a/src/components/Gradebook/index.jsx
+++ b/src/components/Gradebook/index.jsx
@@ -52,134 +52,6 @@ export default class Gradebook extends React.Component {
});
}
- sortAlphaDesc = (gradeRowA, gradeRowB) => {
- const a = gradeRowA.username.toUpperCase();
- const b = gradeRowB.username.toUpperCase();
- if (a < b) {
- return -1;
- }
- if (a > b) {
- return 1;
- }
- return 0;
- };
-
- sortAlphaAsc = (gradeRowA, gradeRowB) => {
- const a = gradeRowA.username.toUpperCase();
- const b = gradeRowB.username.toUpperCase();
- if (a < b) {
- return 1;
- }
- if (a > b) {
- return -1;
- }
- return 0;
- };
-
- sortNumerically = (colKey, direction) => {
- function sortNumAsc(gradeRowA, gradeRowB) {
- if (gradeRowA[colKey] < gradeRowB[colKey]) {
- return -1;
- }
- if (gradeRowA[colKey] > gradeRowB[colKey]) {
- return 1;
- }
- return 0;
- }
-
- function sortNumDesc(gradeRowA, gradeRowB) {
- if (gradeRowA[colKey] < gradeRowB[colKey]) {
- return 1;
- }
- if (gradeRowA[colKey] > gradeRowB[colKey]) {
- return -1;
- }
- return 0;
- }
-
- this.setState({ grades: [...this.state.grades].sort(direction === 'desc' ? sortNumDesc : sortNumAsc) });
- }
-
- mapHeadings = (entry) => {
- if (entry) {
- const results = [{
- label: 'Username',
- key: 'username',
- columnSortable: true,
- onSort: (direction) => {
- this.setState({
- grades: [...this.state.grades].sort(direction === 'desc' ? this.sortAlphaDesc : this.sortAlphaAsc),
- });
- },
- }];
-
- const assignmentHeadings = entry.section_breakdown
- .filter(section => section.is_graded && section.label)
- .map(s => ({
- label: s.label,
- key: s.label,
- columnSortable: true,
- onSort: (direction) => { this.sortNumerically(s.label, direction); },
- }));
-
- const totals = [{
- label: 'Total',
- key: 'total',
- columnSortable: true,
- onSort: (direction) => { this.sortNumerically('total', direction); },
- }];
-
- return results.concat(assignmentHeadings).concat(totals);
- }
- return [];
- };
-
- mapHeadingsHw = (entry) => {
- const results = [{
- label: 'Username',
- key: 'username',
- columnSortable: true,
- onSort: (direction) => {
- this.setState({
- grades: [...this.state.grades].sort(direction === 'desc' ? this.sortAlphaDesc : this.sortAlphaAsc),
- });
- },
- }];
- const assignmentHeadings = entry.section_breakdown
- .filter(section => section.is_graded && section.label && section.category == 'Homework')
- .map(s => ({
- label: s.label,
- key: s.label,
- columnSortable: true,
- onSort: (direction) => { this.sortNumerically(s.label, direction); },
- }));
-
- return results.concat(assignmentHeadings);
- };
-
- mapHeadingsExam = (entry) => {
- const results = [{
- label: 'Username',
- key: 'username',
- columnSortable: true,
- onSort: (direction) => {
- this.setState({
- grades: [...this.state.grades].sort(direction === 'desc' ? this.sortAlphaDesc : this.sortAlphaAsc),
- });
- },
- }];
- const assignmentHeadings = entry.section_breakdown
- .filter(section => section.is_graded && section.label && section.category == 'Exam')
- .map(s => ({
- label: s.label,
- key: s.label,
- columnSortable: true,
- onSort: (direction) => { this.sortNumerically(s.label, direction); },
- }));
-
- return results.concat(assignmentHeadings);
- };
-
handleAdjustedGradeClick = () => {
this.props.updateGrades(this.props.match.params.courseId, [
{
@@ -345,8 +217,7 @@ export default class Gradebook extends React.Component {
type="radio"
name="category"
value="all"
- onClick={() =>
- this.setState({ headings: this.mapHeadings(this.props.results[0]) })}
+ onClick={() => this.props.filterColumns('all', this.props.grades[0])}
/>
All
@@ -358,10 +229,7 @@ export default class Gradebook extends React.Component {
type="radio"
name="category"
value="homework"
- onClick={() =>
- this.setState({
- headings: this.mapHeadingsHw(this.props.results[0]),
- })}
+ onClick={() => this.props.filterColumns('hw', this.props.grades[0])}
/>
@@ -372,7 +240,7 @@ export default class Gradebook extends React.Component {
type="radio"
name="category"
value="exam"
- onClick={() => this.setState({ headings: this.mapHeadingsExam(this.props.results[0]) })}
+ onClick={() => this.props.filterColumns('exam', this.props.grades[0])}
/>
Exam
@@ -417,9 +285,8 @@ export default class Gradebook extends React.Component {
diff --git a/src/containers/GradebookPage/index.jsx b/src/containers/GradebookPage/index.jsx
index 2fbf9f2..24848b9 100644
--- a/src/containers/GradebookPage/index.jsx
+++ b/src/containers/GradebookPage/index.jsx
@@ -6,6 +6,7 @@ import {
fetchMatchingUserGrades,
updateGrades,
toggleGradeFormat,
+ filterColumns,
} from '../../data/actions/grades';
import { fetchCohorts } from '../../data/actions/cohorts';
import { fetchTracks } from '../../data/actions/tracks';
@@ -13,6 +14,7 @@ import { fetchTracks } from '../../data/actions/tracks';
const mapStateToProps = state => (
{
grades: state.grades.results,
+ headings: state.grades.headings,
tracks: state.tracks.results,
cohorts: state.cohorts.results,
selectedTrack: state.grades.selectedTrack,
@@ -41,6 +43,9 @@ const mapDispatchToProps = dispatch => (
toggleFormat: (formatType) => {
dispatch(toggleGradeFormat(formatType));
},
+ filterColumns: (filterType, exampleUser) => {
+ dispatch(filterColumns(filterType, exampleUser));
+ },
}
);
diff --git a/src/data/actions/grades.js b/src/data/actions/grades.js
index 95f2db8..745aac1 100644
--- a/src/data/actions/grades.js
+++ b/src/data/actions/grades.js
@@ -7,17 +7,21 @@ import {
GRADE_UPDATE_SUCCESS,
GRADE_UPDATE_FAILURE,
TOGGLE_GRADE_FORMAT,
+ SORT_GRADES,
+ FILTER_COLUMNS,
} from '../constants/actionTypes/grades';
import LmsApiService from '../services/LmsApiService';
+import { headingMapper } from './utils';
const startedFetchingGrades = () => ({ type: STARTED_FETCHING_GRADES });
const finishedFetchingGrades = () => ({ type: FINISHED_FETCHING_GRADES });
const errorFetchingGrades = () => ({ type: ERROR_FETCHING_GRADES });
-const gotGrades = (grades, cohort, track) => ({
+const gotGrades = (grades, cohort, track, headings) => ({
type: GOT_GRADES,
grades,
cohort,
track,
+ headings,
});
const gradeUpdateRequest = () => ({ type: GRADE_UPDATE_REQUEST });
@@ -32,7 +36,12 @@ const gradeUpdateFailure = error => ({
const toggleGradeFormat = formatType => ({ type: TOGGLE_GRADE_FORMAT, formatType });
+const sortGrades = (columnName, direction) => ({ type: SORT_GRADES, columnName, direction });
+const filterColumns = (filterType, exampleUser) => ({
+ type: FILTER_COLUMNS,
+ headings: headingMapper[filterType](exampleUser)
+});
const fetchGrades = (courseId, cohort, track) => (
(dispatch) => {
@@ -40,7 +49,7 @@ const fetchGrades = (courseId, cohort, track) => (
return LmsApiService.fetchGradebookData(courseId, null, cohort, track)
.then(response => response.data)
.then((data) => {
- dispatch(gotGrades(data.results, cohort, track));
+ dispatch(gotGrades(data.results, cohort, track, headingMapper.all(data.results[0])));
dispatch(finishedFetchingGrades());
})
.catch(() => {
@@ -70,7 +79,7 @@ const updateGrades = (courseId, updateData) => (
return LmsApiService.updateGradebookData(courseId, updateData)
.then(response => response.data)
.then((data) => {
- dispatch(gradeUpdateSuccess(data))
+ dispatch(gradeUpdateSuccess(data));
})
.catch((error) => {
dispatch(gradeUpdateFailure(error));
@@ -90,4 +99,6 @@ export {
gradeUpdateFailure,
updateGrades,
toggleGradeFormat,
+ sortGrades,
+ filterColumns,
};
diff --git a/src/data/actions/utils.js b/src/data/actions/utils.js
new file mode 100644
index 0000000..23088a7
--- /dev/null
+++ b/src/data/actions/utils.js
@@ -0,0 +1,131 @@
+
+const sortAlphaDesc = (gradeRowA, gradeRowB) => {
+ const a = gradeRowA.username.toUpperCase();
+ const b = gradeRowB.username.toUpperCase();
+ if (a < b) {
+ return -1;
+ }
+ if (a > b) {
+ return 1;
+ }
+ return 0;
+};
+
+const sortAlphaAsc = (gradeRowA, gradeRowB) => {
+ const a = gradeRowA.username.toUpperCase();
+ const b = gradeRowB.username.toUpperCase();
+ if (a < b) {
+ return 1;
+ }
+ if (a > b) {
+ return -1;
+ }
+ return 0;
+};
+
+const sortNumerically = (colKey, direction) => {
+ function sortNumAsc(gradeRowA, gradeRowB) {
+ if (gradeRowA[colKey] < gradeRowB[colKey]) {
+ return -1;
+ }
+ if (gradeRowA[colKey] > gradeRowB[colKey]) {
+ return 1;
+ }
+ return 0;
+ }
+
+ function sortNumDesc(gradeRowA, gradeRowB) {
+ if (gradeRowA[colKey] < gradeRowB[colKey]) {
+ return 1;
+ }
+ if (gradeRowA[colKey] > gradeRowB[colKey]) {
+ return -1;
+ }
+ return 0;
+ }
+
+ this.setState({ grades: [...this.state.grades].sort(direction === 'desc' ? sortNumDesc : sortNumAsc) });
+};
+const headingMapper = {
+ all: (entry) => {
+ if (entry) {
+ const results = [{
+ label: 'Username',
+ key: 'username',
+ columnSortable: true,
+ onSort: (direction) => {
+ this.setState({
+ grades: [...this.state.grades].sort(direction === 'desc' ? this.sortAlphaDesc : this.sortAlphaAsc),
+ });
+ },
+ }];
+
+ const assignmentHeadings = entry.section_breakdown
+ .filter(section => section.is_graded && section.label)
+ .map(s => ({
+ label: s.label,
+ key: s.label,
+ columnSortable: true,
+ onSort: (direction) => { this.sortNumerically(s.label, direction); },
+ }));
+
+ const totals = [{
+ label: 'Total',
+ key: 'total',
+ columnSortable: true,
+ onSort: (direction) => { this.sortNumerically('total', direction); },
+ }];
+
+ return results.concat(assignmentHeadings).concat(totals);
+ }
+ return [];
+ },
+ hw: (entry) => {
+ const results = [{
+ label: 'Username',
+ key: 'username',
+ columnSortable: true,
+ onSort: (direction) => {
+ this.setState({
+ grades: [...this.state.grades].sort(direction === 'desc' ? this.sortAlphaDesc : this.sortAlphaAsc),
+ });
+ },
+ }];
+
+ const assignmentHeadings = entry.section_breakdown
+ .filter(section => section.is_graded && section.label && section.category == 'Homework')
+ .map(s => ({
+ label: s.label,
+ key: s.label,
+ columnSortable: false,
+ onSort: (direction) => { this.sortNumerically(s.label, direction); },
+ }));
+
+ return results.concat(assignmentHeadings);
+ },
+ exam: (entry) => {
+ const results = [{
+ label: 'Username',
+ key: 'username',
+ columnSortable: false,
+ onSort: (direction) => {
+ this.setState({
+ grades: [...this.state.grades].sort(direction === 'desc' ? this.sortAlphaDesc : this.sortAlphaAsc),
+ });
+ },
+ }];
+
+ const assignmentHeadings = entry.section_breakdown
+ .filter(section => section.is_graded && section.label && section.category == 'Exam')
+ .map(s => ({
+ label: s.label,
+ key: s.label,
+ columnSortable: false,
+ onSort: (direction) => { this.sortNumerically(s.label, direction); },
+ }));
+
+ return results.concat(assignmentHeadings);
+ },
+};
+
+export { headingMapper };
diff --git a/src/data/constants/actionTypes/grades.js b/src/data/constants/actionTypes/grades.js
index 6aa4d17..31a65d6 100644
--- a/src/data/constants/actionTypes/grades.js
+++ b/src/data/constants/actionTypes/grades.js
@@ -8,6 +8,8 @@ const GRADE_UPDATE_SUCCESS = 'GRADE_UPDATE_SUCCESS';
const GRADE_UPDATE_FAILURE = 'GRADE_UPDATE_FAILURE';
const TOGGLE_GRADE_FORMAT = 'TOGGLE_GRADE_FORMAT';
+const SORT_GRADES = 'SORT_GRADES';
+const FILTER_COLUMNS = 'FILTER_COLUMNS';
export {
STARTED_FETCHING_GRADES,
@@ -18,4 +20,6 @@ export {
GRADE_UPDATE_SUCCESS,
GRADE_UPDATE_FAILURE,
TOGGLE_GRADE_FORMAT,
+ SORT_GRADES,
+ FILTER_COLUMNS,
};
diff --git a/src/data/reducers/grades.js b/src/data/reducers/grades.js
index cbbcc36..a11f46e 100644
--- a/src/data/reducers/grades.js
+++ b/src/data/reducers/grades.js
@@ -3,10 +3,12 @@ import {
ERROR_FETCHING_GRADES,
GOT_GRADES,
TOGGLE_GRADE_FORMAT,
+ FILTER_COLUMNS,
} from '../constants/actionTypes/grades';
const initialState = {
results: [],
+ headings: [],
startedFetching: false,
finishedFetching: false,
errorFetching: false,
@@ -19,6 +21,7 @@ const grades = (state = initialState, action) => {
return {
...state,
results: action.grades,
+ headings: action.headings,
finishedFetching: true,
errorFetching: false,
selectedTrack: action.track,
@@ -41,6 +44,11 @@ const grades = (state = initialState, action) => {
...state,
gradeFormat: action.formatType,
};
+ case FILTER_COLUMNS:
+ return {
+ ...state,
+ headings: action.headings,
+ };
default:
return state;
}