Fix the category filter

This commit is contained in:
Rick Reilly
2018-11-14 14:55:17 -05:00
parent df32123f34
commit c660bd8d15
6 changed files with 166 additions and 140 deletions

View File

@@ -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
</label>
@@ -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])}
/>
<label className="ml-2 mr-2" htmlFor="category-homework">Homework</label>
</span>
@@ -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
</label>
@@ -417,9 +285,8 @@ export default class Gradebook extends React.Component {
<br />
<div className="gbook">
<Table
columns={this.mapHeadings(this.props.grades[0])}
columns={this.props.headings}
data={this.formatter[this.props.format](this.props.grades)}
tableSortable
defaultSortDirection="desc"
defaultSortedColumn="username"
/>

View File

@@ -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));
},
}
);

View File

@@ -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,
};

131
src/data/actions/utils.js Normal file
View File

@@ -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 };

View File

@@ -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,
};

View File

@@ -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;
}