linting
This commit is contained in:
@@ -14,11 +14,6 @@ export default class Drawer extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
deferToNextRepaint(callback) {
|
||||
window.requestAnimationFrame(() =>
|
||||
window.setTimeout(callback, 0));
|
||||
}
|
||||
|
||||
close = () => {
|
||||
if (this.state.open) {
|
||||
this.toggleOpen();
|
||||
@@ -39,6 +34,10 @@ export default class Drawer extends React.Component {
|
||||
}
|
||||
};
|
||||
|
||||
deferToNextRepaint(callback) {
|
||||
window.requestAnimationFrame(() => window.setTimeout(callback, 0));
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="d-flex drawer-container">
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import React from 'react';
|
||||
@@ -27,27 +26,43 @@ function RangeFilterBadge({
|
||||
filterValue2,
|
||||
handleBadgeClose,
|
||||
}) {
|
||||
return ((filterValue1 !== initialFilters[filterName1]) ||
|
||||
(filterValue2 !== initialFilters[filterName2]))
|
||||
&&
|
||||
return ((filterValue1 !== initialFilters[filterName1])
|
||||
|| (filterValue2 !== initialFilters[filterName2]))
|
||||
&& (
|
||||
<FilterBadge
|
||||
name={displayName}
|
||||
value={`${filterValue1} - ${filterValue2}`}
|
||||
onClick={handleBadgeClose}
|
||||
/>;
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
RangeFilterBadge.propTypes = {
|
||||
displayName: PropTypes.string.isRequired,
|
||||
filterName1: PropTypes.string.isRequired,
|
||||
filterValue1: PropTypes.string.isRequired,
|
||||
filterName2: PropTypes.string.isRequired,
|
||||
filterValue2: PropTypes.string.isRequired,
|
||||
handleBadgeClose: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
function SingleValueFilterBadge({
|
||||
displayName, filterName, filterValue, handleBadgeClose,
|
||||
}) {
|
||||
return (filterValue !== initialFilters[filterName]) &&
|
||||
return (filterValue !== initialFilters[filterName])
|
||||
&& (
|
||||
<FilterBadge
|
||||
name={displayName}
|
||||
value={filterValue}
|
||||
onClick={handleBadgeClose}
|
||||
/>;
|
||||
/>
|
||||
);
|
||||
}
|
||||
SingleValueFilterBadge.propTypes = {
|
||||
displayName: PropTypes.string.isRequired,
|
||||
filterName: PropTypes.string.isRequired,
|
||||
filterValue: PropTypes.string.isRequired,
|
||||
handleBadgeClose: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
function FilterBadges({
|
||||
assignment,
|
||||
@@ -150,4 +165,3 @@ FilterBadges.propTypes = {
|
||||
courseGradeMax: PropTypes.string,
|
||||
handleFilterBadgeClose: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable react/sort-comp, react/button-has-type */
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
@@ -24,7 +25,6 @@ import { formatDateForDisplay } from '../../data/actions/utils';
|
||||
import initialFilters from '../../data/constants/filters';
|
||||
import ConnectedFilterBadges from '../FilterBadges';
|
||||
|
||||
|
||||
const DECIMAL_PRECISION = 2;
|
||||
const GRADE_OVERRIDE_HISTORY_COLUMNS = [{ label: 'Date', key: 'date' }, { label: 'Grader', key: 'grader' },
|
||||
{ label: 'Reason', key: 'reason' },
|
||||
@@ -166,8 +166,7 @@ export default class Gradebook extends React.Component {
|
||||
};
|
||||
|
||||
handleAssignmentFilterChange = (assignment) => {
|
||||
const selectedFilterOption = this.props.assignmentFilterOptions.find(assig =>
|
||||
assig.label === assignment);
|
||||
const selectedFilterOption = this.props.assignmentFilterOptions.find(assig => assig.label === assignment);
|
||||
const { type, id } = selectedFilterOption || {};
|
||||
const typedValue = { label: assignment, type, id };
|
||||
this.props.updateAssignmentFilter(typedValue);
|
||||
@@ -396,7 +395,8 @@ export default class Gradebook extends React.Component {
|
||||
onClick={() => this.setNewModalState(entry, subsection)}
|
||||
>
|
||||
{this.roundGrade(subsection.percent * 100)}%
|
||||
</button>);
|
||||
</button>
|
||||
);
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
@@ -550,47 +550,45 @@ export default class Gradebook extends React.Component {
|
||||
href={this.lmsInstructorDashboardUrl(this.props.courseId)}
|
||||
className="mb-3"
|
||||
>
|
||||
<span aria-hidden="true">{'<< '}</span> {'Back to Dashboard'}
|
||||
<span aria-hidden="true">{'<< '}</span> Back to Dashboard
|
||||
</a>
|
||||
<h1>Gradebook</h1>
|
||||
<h3> {this.props.courseId}</h3>
|
||||
{this.props.areGradesFrozen &&
|
||||
<div className="alert alert-warning" role="alert" >
|
||||
{this.props.areGradesFrozen
|
||||
&& (
|
||||
<div className="alert alert-warning" role="alert">
|
||||
The grades for this course are now frozen. Editing of grades is no longer allowed.
|
||||
</div>
|
||||
}
|
||||
{(this.props.canUserViewGradebook === false) &&
|
||||
<div className="alert alert-warning" role="alert" >
|
||||
)}
|
||||
{(this.props.canUserViewGradebook === false)
|
||||
&& (
|
||||
<div className="alert alert-warning" role="alert">
|
||||
You are not authorized to view the gradebook for this course.
|
||||
</div>
|
||||
}
|
||||
)}
|
||||
<Tabs defaultActiveKey="grades">
|
||||
<Tab eventKey="grades" title="Grades">
|
||||
<h4>Step 1: Filter the Grade Report</h4>
|
||||
<div className="d-flex justify-content-between" >
|
||||
<div className="d-flex justify-content-between">
|
||||
{this.props.showSpinner && <div className="spinner-overlay"><Icon className="fa fa-spinner fa-spin fa-5x color-black" /></div>}
|
||||
<Button className="btn-primary align-self-start" onClick={toggleFilterDrawer}><FontAwesomeIcon icon={faFilter} /> Edit Filters</Button>
|
||||
<div>
|
||||
<SearchField
|
||||
onSubmit={value =>
|
||||
this.props.searchForUser(
|
||||
this.props.courseId,
|
||||
value,
|
||||
this.props.selectedCohort,
|
||||
this.props.selectedTrack,
|
||||
this.props.selectedAssignmentType,
|
||||
)
|
||||
}
|
||||
onSubmit={value => this.props.searchForUser(
|
||||
this.props.courseId,
|
||||
value,
|
||||
this.props.selectedCohort,
|
||||
this.props.selectedTrack,
|
||||
this.props.selectedAssignmentType,
|
||||
)}
|
||||
inputLabel="Search for a learner"
|
||||
onChange={filterValue => this.setState({ filterValue })}
|
||||
onClear={() =>
|
||||
this.props.getUserGrades(
|
||||
this.props.courseId,
|
||||
this.props.selectedCohort,
|
||||
this.props.selectedTrack,
|
||||
this.props.selectedAssignmentType,
|
||||
)
|
||||
}
|
||||
onClear={() => this.props.getUserGrades(
|
||||
this.props.courseId,
|
||||
this.props.selectedCohort,
|
||||
this.props.selectedTrack,
|
||||
this.props.selectedAssignmentType,
|
||||
)}
|
||||
value={this.state.filterValue}
|
||||
/>
|
||||
<small className="form-text text-muted search-help-text">Search by username, email, or student key</small>
|
||||
@@ -610,21 +608,22 @@ export default class Gradebook extends React.Component {
|
||||
dialog={this.getCourseGradeFilterAlertDialog()}
|
||||
dismissible={false}
|
||||
open={
|
||||
!this.state.isMinCourseGradeFilterValid ||
|
||||
!this.state.isMaxCourseGradeFilterValid
|
||||
!this.state.isMinCourseGradeFilterValid
|
||||
|| !this.state.isMaxCourseGradeFilterValid
|
||||
}
|
||||
/>
|
||||
<h4>Step 2: View or Modify Individual Grades</h4>
|
||||
{this.props.totalUsersCount ?
|
||||
<div>
|
||||
Showing
|
||||
<span className="font-weight-bold"> {this.props.filteredUsersCount} </span>
|
||||
of
|
||||
<span className="font-weight-bold"> {this.props.totalUsersCount} </span>
|
||||
total learners
|
||||
</div> :
|
||||
null
|
||||
}
|
||||
{this.props.totalUsersCount
|
||||
? (
|
||||
<div>
|
||||
Showing
|
||||
<span className="font-weight-bold"> {this.props.filteredUsersCount} </span>
|
||||
of
|
||||
<span className="font-weight-bold"> {this.props.totalUsersCount} </span>
|
||||
total learners
|
||||
</div>
|
||||
)
|
||||
: null}
|
||||
<div className="d-flex justify-content-between align-items-center mb-2">
|
||||
<InputSelect
|
||||
label="Score View:"
|
||||
@@ -727,10 +726,11 @@ export default class Gradebook extends React.Component {
|
||||
|| this.props.gradeOriginalPossibleGraded}
|
||||
</span>),
|
||||
}]}
|
||||
/>)}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div>Showing most recent actions (max 5). To see more, please contact
|
||||
support.
|
||||
support.
|
||||
</div>
|
||||
<div>Note: Once you save, your changes will be visible to students.</div>
|
||||
</div>
|
||||
@@ -814,16 +814,17 @@ export default class Gradebook extends React.Component {
|
||||
]}
|
||||
className="table-striped"
|
||||
/>
|
||||
</Tab>)}
|
||||
</Tab>
|
||||
)}
|
||||
</Tabs>
|
||||
</div>
|
||||
)}
|
||||
initiallyOpen={false}
|
||||
title={
|
||||
<React.Fragment>
|
||||
title={(
|
||||
<>
|
||||
<FontAwesomeIcon icon={faFilter} /> Filter By...
|
||||
</React.Fragment>
|
||||
}
|
||||
</>
|
||||
)}
|
||||
>
|
||||
<Collapsible title="Assignments" open className="filter-group mb-3">
|
||||
<div>
|
||||
|
||||
@@ -2,7 +2,6 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button } from '@edx/paragon';
|
||||
|
||||
|
||||
export default function PageButtons({
|
||||
prevPage, nextPage, selectedTrack, selectedCohort, selectedAssignmentType,
|
||||
getPrevNextGrades, match,
|
||||
@@ -16,14 +15,13 @@ export default function PageButtons({
|
||||
style={{ margin: '20px' }}
|
||||
variant="outline-primary"
|
||||
disabled={!prevPage}
|
||||
onClick={() =>
|
||||
getPrevNextGrades(
|
||||
prevPage,
|
||||
match.params.courseId,
|
||||
selectedCohort,
|
||||
selectedTrack,
|
||||
selectedAssignmentType,
|
||||
)}
|
||||
onClick={() => getPrevNextGrades(
|
||||
prevPage,
|
||||
match.params.courseId,
|
||||
selectedCohort,
|
||||
selectedTrack,
|
||||
selectedAssignmentType,
|
||||
)}
|
||||
>
|
||||
Previous Page
|
||||
</Button>
|
||||
@@ -31,14 +29,13 @@ export default function PageButtons({
|
||||
style={{ margin: '20px' }}
|
||||
variant="outline-primary"
|
||||
disabled={!nextPage}
|
||||
onClick={() =>
|
||||
getPrevNextGrades(
|
||||
nextPage,
|
||||
match.params.courseId,
|
||||
selectedCohort,
|
||||
selectedTrack,
|
||||
selectedAssignmentType,
|
||||
)}
|
||||
onClick={() => getPrevNextGrades(
|
||||
nextPage,
|
||||
match.params.courseId,
|
||||
selectedCohort,
|
||||
selectedTrack,
|
||||
selectedAssignmentType,
|
||||
)}
|
||||
>
|
||||
Next Page
|
||||
</Button>
|
||||
@@ -76,4 +73,3 @@ PageButtons.propTypes = {
|
||||
name: PropTypes.string,
|
||||
}),
|
||||
};
|
||||
|
||||
|
||||
@@ -18,7 +18,9 @@ import {
|
||||
} from '../../data/actions/grades';
|
||||
import { fetchCohorts } from '../../data/actions/cohorts';
|
||||
import { fetchTracks } from '../../data/actions/tracks';
|
||||
import { initializeFilters, resetFilters, updateAssignmentFilter, updateAssignmentLimits, updateCourseGradeFilter } from '../../data/actions/filters';
|
||||
import {
|
||||
initializeFilters, resetFilters, updateAssignmentFilter, updateAssignmentLimits, updateCourseGradeFilter,
|
||||
} from '../../data/actions/filters';
|
||||
import stateHasMastersTrack from '../../data/selectors/tracks';
|
||||
import {
|
||||
getBulkManagementHistory,
|
||||
@@ -37,7 +39,7 @@ import LmsApiService from '../../data/services/LmsApiService';
|
||||
function shouldShowSpinner(state) {
|
||||
if (state.roles.canUserViewGradebook === true) {
|
||||
return state.grades.showSpinner;
|
||||
} else if (state.roles.canUserViewGradebook === false) {
|
||||
} if (state.roles.canUserViewGradebook === false) {
|
||||
return false;
|
||||
} // canUserViewGradebook === null
|
||||
return true;
|
||||
@@ -104,12 +106,12 @@ const mapStateToProps = (state, ownProps) => (
|
||||
courseGradeMin: formatMinCourseGrade(state.filters.courseGradeMin),
|
||||
courseGradeMax: formatMaxCourseGrade(state.filters.courseGradeMax),
|
||||
}),
|
||||
bulkImportError: state.grades.bulkManagement &&
|
||||
state.grades.bulkManagement.errorMessages ?
|
||||
`Errors while processing: ${state.grades.bulkManagement.errorMessages.join(', ')}` :
|
||||
'',
|
||||
uploadSuccess: !!(state.grades.bulkManagement &&
|
||||
state.grades.bulkManagement.uploadSuccess),
|
||||
bulkImportError: state.grades.bulkManagement
|
||||
&& state.grades.bulkManagement.errorMessages
|
||||
? `Errors while processing: ${state.grades.bulkManagement.errorMessages.join(', ')}`
|
||||
: '',
|
||||
uploadSuccess: !!(state.grades.bulkManagement
|
||||
&& state.grades.bulkManagement.uploadSuccess),
|
||||
showBulkManagement: stateHasMastersTrack(state) && state.config.bulkManagementAvailable,
|
||||
bulkManagementHistory: getBulkManagementHistory(state),
|
||||
totalUsersCount: state.grades.totalUsersCount,
|
||||
|
||||
@@ -38,4 +38,3 @@ export {
|
||||
gotAssignmentTypes,
|
||||
errorFetchingAssignmentTypes,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import initialFilters from '../constants/filters';
|
||||
import { INITIALIZE_FILTERS, RESET_FILTERS, UPDATE_ASSIGNMENT_FILTER, UPDATE_ASSIGNMENT_LIMITS, UPDATE_COURSE_GRADE_LIMITS } from '../constants/actionTypes/filters';
|
||||
import {
|
||||
INITIALIZE_FILTERS, RESET_FILTERS, UPDATE_ASSIGNMENT_FILTER, UPDATE_ASSIGNMENT_LIMITS, UPDATE_COURSE_GRADE_LIMITS,
|
||||
} from '../constants/actionTypes/filters';
|
||||
|
||||
const initializeFilters = ({
|
||||
assignment = initialFilters.assignment,
|
||||
|
||||
@@ -26,7 +26,9 @@ import {
|
||||
} from '../constants/actionTypes/grades';
|
||||
import LmsApiService from '../services/LmsApiService';
|
||||
import { sortAlphaAsc, formatDateForDisplay } from './utils';
|
||||
import { formatMaxAssignmentGrade, formatMinAssignmentGrade, formatMaxCourseGrade, formatMinCourseGrade } from '../selectors/grades';
|
||||
import {
|
||||
formatMaxAssignmentGrade, formatMinAssignmentGrade, formatMaxCourseGrade, formatMinCourseGrade,
|
||||
} from '../selectors/grades';
|
||||
import { getFilters } from '../selectors/filters';
|
||||
|
||||
const defaultAssignmentFilter = 'All';
|
||||
@@ -108,7 +110,6 @@ const uploadOverrideFailure = (courseId, error) => ({
|
||||
payload: { error },
|
||||
});
|
||||
|
||||
|
||||
const toggleGradeFormat = formatType => ({ type: TOGGLE_GRADE_FORMAT, formatType });
|
||||
|
||||
const filterAssignmentType = filterType => (
|
||||
@@ -191,27 +192,26 @@ const doneViewingAssignment = () => dispatch => dispatch({
|
||||
type: DONE_VIEWING_ASSIGNMENT,
|
||||
});
|
||||
const fetchGradeOverrideHistory = (subsectionId, userId) => (
|
||||
dispatch =>
|
||||
LmsApiService.fetchGradeOverrideHistory(subsectionId, userId)
|
||||
.then(response => response.data)
|
||||
.then((data) => {
|
||||
dispatch(gotGradeOverrideHistory({
|
||||
overrideHistory: formatGradeOverrideForDisplay(data.history),
|
||||
currentEarnedAllOverride: data.override ? data.override.earned_all_override : null,
|
||||
currentPossibleAllOverride: data.override ? data.override.possible_all_override : null,
|
||||
currentEarnedGradedOverride: data.override ? data.override.earned_graded_override : null,
|
||||
currentPossibleGradedOverride: data.override ?
|
||||
data.override.possible_graded_override : null,
|
||||
originalGradeEarnedAll: data.original_grade ? data.original_grade.earned_all : null,
|
||||
originalGradePossibleAll: data.original_grade ? data.original_grade.possible_all : null,
|
||||
originalGradeEarnedGraded: data.original_grade ? data.original_grade.earned_graded : null,
|
||||
originalGradePossibleGraded: data.original_grade ?
|
||||
data.original_grade.possible_graded : null,
|
||||
}));
|
||||
})
|
||||
.catch(() => {
|
||||
dispatch(errorFetchingGradeOverrideHistory());
|
||||
})
|
||||
dispatch => LmsApiService.fetchGradeOverrideHistory(subsectionId, userId)
|
||||
.then(response => response.data)
|
||||
.then((data) => {
|
||||
dispatch(gotGradeOverrideHistory({
|
||||
overrideHistory: formatGradeOverrideForDisplay(data.history),
|
||||
currentEarnedAllOverride: data.override ? data.override.earned_all_override : null,
|
||||
currentPossibleAllOverride: data.override ? data.override.possible_all_override : null,
|
||||
currentEarnedGradedOverride: data.override ? data.override.earned_graded_override : null,
|
||||
currentPossibleGradedOverride: data.override
|
||||
? data.override.possible_graded_override : null,
|
||||
originalGradeEarnedAll: data.original_grade ? data.original_grade.earned_all : null,
|
||||
originalGradePossibleAll: data.original_grade ? data.original_grade.possible_all : null,
|
||||
originalGradeEarnedGraded: data.original_grade ? data.original_grade.earned_graded : null,
|
||||
originalGradePossibleGraded: data.original_grade
|
||||
? data.original_grade.possible_graded : null,
|
||||
}));
|
||||
})
|
||||
.catch(() => {
|
||||
dispatch(errorFetchingGradeOverrideHistory());
|
||||
})
|
||||
);
|
||||
|
||||
const fetchMatchingUserGrades = (
|
||||
@@ -293,11 +293,10 @@ const submitFileUploadFormData = (courseId, formData) => (
|
||||
);
|
||||
|
||||
const fetchBulkUpgradeHistory = courseId => (
|
||||
dispatch =>
|
||||
// todo add loading effect
|
||||
LmsApiService.fetchGradeBulkOperationHistory(courseId).then((response) => {
|
||||
dispatch(gotBulkHistory(response));
|
||||
}).catch(() => dispatch(bulkHistoryError()))
|
||||
// todo add loading effect
|
||||
dispatch => LmsApiService.fetchGradeBulkOperationHistory(courseId).then(
|
||||
(response) => { dispatch(gotBulkHistory(response)); },
|
||||
).catch(() => dispatch(bulkHistoryError()))
|
||||
);
|
||||
|
||||
const updateGradesIfAssignmentGradeFiltersSet = (
|
||||
|
||||
@@ -14,7 +14,6 @@ import {
|
||||
} from '../constants/actionTypes/grades';
|
||||
import { sortAlphaAsc } from './utils';
|
||||
|
||||
|
||||
const mockStore = configureMockStore([thunk]);
|
||||
|
||||
jest.mock('@edx/frontend-platform/auth');
|
||||
|
||||
@@ -15,7 +15,6 @@ import { STARTED_FETCHING_TRACKS } from '../constants/actionTypes/tracks';
|
||||
import { STARTED_FETCHING_COHORTS } from '../constants/actionTypes/cohorts';
|
||||
import { STARTED_FETCHING_ASSIGNMENT_TYPES } from '../constants/actionTypes/assignmentTypes';
|
||||
|
||||
|
||||
const mockStore = configureMockStore([thunk]);
|
||||
|
||||
jest.mock('@edx/frontend-platform/auth');
|
||||
|
||||
@@ -27,4 +27,3 @@ const sortAlphaAsc = (gradeRowA, gradeRowB) => {
|
||||
};
|
||||
|
||||
export { sortAlphaAsc, formatDateForDisplay };
|
||||
|
||||
|
||||
@@ -9,4 +9,3 @@ export {
|
||||
ERROR_FETCHING_ASSIGNMENT_TYPES,
|
||||
GOT_ARE_GRADES_FROZEN,
|
||||
};
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ const initialState = {
|
||||
errorFetching: false,
|
||||
};
|
||||
|
||||
|
||||
const assignmentTypes = (state = initialState, action) => {
|
||||
switch (action.type) {
|
||||
case GOT_ASSIGNMENT_TYPES:
|
||||
@@ -45,4 +44,3 @@ const assignmentTypes = (state = initialState, action) => {
|
||||
};
|
||||
|
||||
export default assignmentTypes;
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ const initialState = {
|
||||
errorFetching: false,
|
||||
};
|
||||
|
||||
|
||||
const cohorts = (state = initialState, action) => {
|
||||
switch (action.type) {
|
||||
case GOT_COHORTS:
|
||||
@@ -37,4 +36,3 @@ const cohorts = (state = initialState, action) => {
|
||||
};
|
||||
|
||||
export default cohorts;
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { GOT_GRADES, FILTER_BY_ASSIGNMENT_TYPE } from '../constants/actionTypes/grades';
|
||||
|
||||
import { INITIALIZE_FILTERS, UPDATE_ASSIGNMENT_FILTER, UPDATE_ASSIGNMENT_LIMITS, UPDATE_COURSE_GRADE_LIMITS, RESET_FILTERS } from '../constants/actionTypes/filters';
|
||||
import {
|
||||
INITIALIZE_FILTERS, UPDATE_ASSIGNMENT_FILTER, UPDATE_ASSIGNMENT_LIMITS, UPDATE_COURSE_GRADE_LIMITS, RESET_FILTERS,
|
||||
} from '../constants/actionTypes/filters';
|
||||
|
||||
import initialFilters from '../constants/filters';
|
||||
|
||||
@@ -15,8 +17,8 @@ const reducer = (state = initialState, action) => {
|
||||
...state,
|
||||
assignmentType: action.filterType,
|
||||
assignment: (
|
||||
action.filterType !== '' &&
|
||||
(state.assignment || {}).type !== action.filterType)
|
||||
action.filterType !== ''
|
||||
&& (state.assignment || {}).type !== action.filterType)
|
||||
? '' : state.assignment,
|
||||
};
|
||||
case INITIALIZE_FILTERS:
|
||||
|
||||
@@ -10,7 +10,6 @@ const initialState = {
|
||||
errorFetching: false,
|
||||
};
|
||||
|
||||
|
||||
const tracks = (state = initialState, action) => {
|
||||
switch (action.type) {
|
||||
case GOT_TRACKS:
|
||||
@@ -37,4 +36,3 @@ const tracks = (state = initialState, action) => {
|
||||
};
|
||||
|
||||
export default tracks;
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
const getCohorts = state => state.cohorts.results || [];
|
||||
|
||||
const getCohortById = (state, selectedCohortId) => {
|
||||
@@ -6,7 +5,6 @@ const getCohortById = (state, selectedCohortId) => {
|
||||
return cohort;
|
||||
};
|
||||
|
||||
const getCohortNameById = (state, selectedCohortId) =>
|
||||
(getCohortById(state, selectedCohortId) || {}).name;
|
||||
const getCohortNameById = (state, selectedCohortId) => (getCohortById(state, selectedCohortId) || {}).name;
|
||||
|
||||
export { getCohortById, getCohortNameById, getCohorts };
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
const getFilters = state => state.filters || {};
|
||||
|
||||
const getAssignmentsFromResultsSubstate = results =>
|
||||
(results[0] || {}).section_breakdown || [];
|
||||
const getAssignmentsFromResultsSubstate = results => (results[0] || {}).section_breakdown || [];
|
||||
|
||||
const selectableAssignments = (state) => {
|
||||
const selectedAssignmentType = getFilters(state).assignmentType;
|
||||
@@ -20,14 +19,12 @@ const chooseRelevantAssignmentData = assignment => ({
|
||||
id: assignment.module_id,
|
||||
});
|
||||
|
||||
const selectableAssignmentLabels = state =>
|
||||
selectableAssignments(state).map(chooseRelevantAssignmentData);
|
||||
const selectableAssignmentLabels = state => selectableAssignments(state).map(chooseRelevantAssignmentData);
|
||||
|
||||
const typeOfSelectedAssignment = (state) => {
|
||||
const selectedAssignmentLabel = getFilters(state).assignment;
|
||||
const sectionBreakdown = (state.grades.results[0] || {}).section_breakdown || [];
|
||||
const selectedAssignment = sectionBreakdown.find(section =>
|
||||
section.label === selectedAssignmentLabel);
|
||||
const selectedAssignment = sectionBreakdown.find(section => section.label === selectedAssignmentLabel);
|
||||
return selectedAssignment && selectedAssignment.category;
|
||||
};
|
||||
|
||||
|
||||
@@ -33,10 +33,8 @@ const transformHistoryEntry = (historyRow) => {
|
||||
...rest,
|
||||
};
|
||||
};
|
||||
const getBulkManagementHistoryFromState = state =>
|
||||
state.grades.bulkManagement.history || [];
|
||||
const getBulkManagementHistory = state =>
|
||||
getBulkManagementHistoryFromState(state).map(transformHistoryEntry);
|
||||
const getBulkManagementHistoryFromState = state => state.grades.bulkManagement.history || [];
|
||||
const getBulkManagementHistory = state => getBulkManagementHistoryFromState(state).map(transformHistoryEntry);
|
||||
|
||||
const headingMapper = (category, label = 'All') => {
|
||||
const filters = {
|
||||
@@ -82,13 +80,12 @@ const getHeadings = (state) => {
|
||||
return headingMapper(type, assignment)(assignments);
|
||||
};
|
||||
|
||||
const composeFilters = (...predicates) => (percentGrade, options = {}) =>
|
||||
predicates.reduce((accum, predicate) => {
|
||||
if (predicate(percentGrade, options)) {
|
||||
return null;
|
||||
}
|
||||
return accum;
|
||||
}, percentGrade);
|
||||
const composeFilters = (...predicates) => (percentGrade, options = {}) => predicates.reduce((accum, predicate) => {
|
||||
if (predicate(percentGrade, options)) {
|
||||
return null;
|
||||
}
|
||||
return accum;
|
||||
}, percentGrade);
|
||||
|
||||
const percentGradeIsMax = percentGrade => (
|
||||
percentGrade === '100'
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
const compose = (...fns) => {
|
||||
const [firstFunc, ...rest] = fns.reverse();
|
||||
return (...args) =>
|
||||
rest.reduce((accum, fn) => fn(accum), firstFunc(...args));
|
||||
return (...args) => rest.reduce((accum, fn) => fn(accum), firstFunc(...args));
|
||||
};
|
||||
|
||||
const getTracks = state => state.tracks.results || [];
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth'
|
||||
import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth';
|
||||
import { configuration } from '../../config';
|
||||
|
||||
class LmsApiService {
|
||||
static baseUrl = configuration.LMS_BASE_URL;
|
||||
|
||||
static pageSize = 25
|
||||
|
||||
static fetchGradebookData(courseId, searchText, cohort, track, options = {}) {
|
||||
@@ -96,8 +97,8 @@ class LmsApiService {
|
||||
static getGradeExportCsvUrl(courseId, options = {}) {
|
||||
const queryParams = ['track', 'cohort', 'assignment', 'assignmentType', 'assignmentGradeMax',
|
||||
'assignmentGradeMin', 'courseGradeMin', 'courseGradeMax']
|
||||
.filter(opt => options[opt] &&
|
||||
options[opt] !== 'All')
|
||||
.filter(opt => options[opt]
|
||||
&& options[opt] !== 'All')
|
||||
.map(opt => `${opt}=${encodeURIComponent(options[opt])}`)
|
||||
.join('&');
|
||||
return `${LmsApiService.baseUrl}/api/bulk_grades/course/${courseId}/?${queryParams}`;
|
||||
@@ -106,8 +107,8 @@ class LmsApiService {
|
||||
static getInterventionExportCsvUrl(courseId, options = {}) {
|
||||
const queryParams = ['track', 'cohort', 'assignment', 'assignmentType', 'assignmentGradeMax',
|
||||
'assignmentGradeMin', 'courseGradeMin', 'courseGradeMax']
|
||||
.filter(opt => options[opt] &&
|
||||
options[opt] !== 'All')
|
||||
.filter(opt => options[opt]
|
||||
&& options[opt] !== 'All')
|
||||
.map(opt => `${opt}=${encodeURIComponent(options[opt])}`)
|
||||
.join('&');
|
||||
return `${LmsApiService.baseUrl}/api/bulk_grades/course/${courseId}/intervention?${queryParams}`;
|
||||
|
||||
@@ -90,7 +90,6 @@ const eventsMap = {
|
||||
|
||||
const segmentMiddleware = createMiddleware(eventsMap, Segment());
|
||||
|
||||
|
||||
const store = createStore(
|
||||
reducers,
|
||||
composeWithDevTools(applyMiddleware(thunkMiddleware, loggerMiddleware, segmentMiddleware)),
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
console.log("index.jsx");
|
||||
import 'babel-polyfill';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
|
||||
@@ -49,51 +47,47 @@ const socialLinks = [
|
||||
},
|
||||
];
|
||||
|
||||
const App = () => {
|
||||
console.log("App");
|
||||
return (
|
||||
<IntlProvider locale='en'>
|
||||
<Provider store={store}>
|
||||
<Router>
|
||||
{ console.log("App Render") }
|
||||
<div>
|
||||
<Header />
|
||||
<main>
|
||||
<Switch>
|
||||
<Route exact path="/:courseId" component={GradebookPage} />
|
||||
</Switch>
|
||||
</main>
|
||||
<SiteFooter
|
||||
siteName={process.env.SITE_NAME}
|
||||
siteLogo={FooterLogo}
|
||||
marketingSiteBaseUrl={process.env.MARKETING_SITE_BASE_URL}
|
||||
supportUrl={process.env.SUPPORT_URL}
|
||||
contactUrl={process.env.CONTACT_URL}
|
||||
openSourceUrl={process.env.OPEN_SOURCE_URL}
|
||||
termsOfServiceUrl={process.env.TERMS_OF_SERVICE_URL}
|
||||
privacyPolicyUrl={process.env.PRIVACY_POLICY_URL}
|
||||
appleAppStoreUrl={process.env.APPLE_APP_STORE_URL}
|
||||
googlePlayUrl={process.env.GOOGLE_PLAY_URL}
|
||||
socialLinks={socialLinks}
|
||||
enterpriseMarketingLink={{
|
||||
url: process.env.ENTERPRISE_MARKETING_URL,
|
||||
queryParams: {
|
||||
utm_source: process.env.ENTERPRISE_MARKETING_UTM_SOURCE,
|
||||
utm_campaign: process.env.ENTERPRISE_MARKETING_UTM_CAMPAIGN,
|
||||
utm_medium: process.env.ENTERPRISE_MARKETING_FOOTER_UTM_MEDIUM,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Router>
|
||||
</Provider>
|
||||
</IntlProvider>
|
||||
);
|
||||
}
|
||||
const App = () => (
|
||||
<IntlProvider locale="en">
|
||||
<Provider store={store}>
|
||||
<Router>
|
||||
<div>
|
||||
<Header />
|
||||
<main>
|
||||
<Switch>
|
||||
<Route exact path="/:courseId" component={GradebookPage} />
|
||||
</Switch>
|
||||
</main>
|
||||
<SiteFooter
|
||||
siteName={process.env.SITE_NAME}
|
||||
siteLogo={FooterLogo}
|
||||
marketingSiteBaseUrl={process.env.MARKETING_SITE_BASE_URL}
|
||||
supportUrl={process.env.SUPPORT_URL}
|
||||
contactUrl={process.env.CONTACT_URL}
|
||||
openSourceUrl={process.env.OPEN_SOURCE_URL}
|
||||
termsOfServiceUrl={process.env.TERMS_OF_SERVICE_URL}
|
||||
privacyPolicyUrl={process.env.PRIVACY_POLICY_URL}
|
||||
appleAppStoreUrl={process.env.APPLE_APP_STORE_URL}
|
||||
googlePlayUrl={process.env.GOOGLE_PLAY_URL}
|
||||
socialLinks={socialLinks}
|
||||
enterpriseMarketingLink={{
|
||||
url: process.env.ENTERPRISE_MARKETING_URL,
|
||||
queryParams: {
|
||||
utm_source: process.env.ENTERPRISE_MARKETING_UTM_SOURCE,
|
||||
utm_campaign: process.env.ENTERPRISE_MARKETING_UTM_CAMPAIGN,
|
||||
utm_medium: process.env.ENTERPRISE_MARKETING_FOOTER_UTM_MEDIUM,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Router>
|
||||
</Provider>
|
||||
</IntlProvider>
|
||||
);
|
||||
|
||||
subscribe(APP_READY, () => {
|
||||
ReactDOM.render(<App />, document.getElementById('root'));
|
||||
})
|
||||
});
|
||||
|
||||
initialize({
|
||||
messages: [
|
||||
@@ -101,5 +95,3 @@ initialize({
|
||||
],
|
||||
requireAuthenticatedUser: true,
|
||||
});
|
||||
|
||||
console.log("end of index.jsx");
|
||||
|
||||
Reference in New Issue
Block a user