chore: update usage of empty submission in list view chore: remove unused test: add unit testing
177 lines
5.0 KiB
JavaScript
177 lines
5.0 KiB
JavaScript
import React from 'react';
|
|
import PropTypes from 'prop-types';
|
|
import { connect } from 'react-redux';
|
|
|
|
import {
|
|
DataTable,
|
|
TextFilter,
|
|
MultiSelectDropdownFilter,
|
|
} from '@edx/paragon';
|
|
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
|
|
|
import { gradingStatuses, submissionFields } from 'data/services/lms/constants';
|
|
import lmsMessages from 'data/services/lms/messages';
|
|
|
|
import { selectors, thunkActions } from 'data/redux';
|
|
|
|
import StatusBadge from 'components/StatusBadge';
|
|
import FilterStatusComponent from './FilterStatusComponent';
|
|
|
|
import messages from './messages';
|
|
|
|
/**
|
|
* <SubmissionsTable />
|
|
*/
|
|
export class SubmissionsTable extends React.Component {
|
|
constructor(props) {
|
|
super(props);
|
|
this.handleViewAllResponsesClick = this.handleViewAllResponsesClick.bind(this);
|
|
this.selectedBulkAction = this.selectedBulkAction.bind(this);
|
|
}
|
|
|
|
get gradeStatusOptions() {
|
|
return Object.keys(gradingStatuses).map(statusKey => ({
|
|
name: this.translate(lmsMessages[gradingStatuses[statusKey]]),
|
|
value: gradingStatuses[statusKey],
|
|
}));
|
|
}
|
|
|
|
get userLabel() {
|
|
return this.translate(this.props.isIndividual ? messages.username : messages.teamName);
|
|
}
|
|
|
|
get userAccessor() {
|
|
return this.props.isIndividual
|
|
? submissionFields.username
|
|
: submissionFields.teamName;
|
|
}
|
|
|
|
get dateSubmittedLabel() {
|
|
return this.translate(this.props.isIndividual
|
|
? messages.learnerSubmissionDate
|
|
: messages.teamSubmissionDate);
|
|
}
|
|
|
|
formatDate = ({ value }) => {
|
|
const date = new Date(value);
|
|
return date.toLocaleString();
|
|
}
|
|
|
|
formatGrade = ({ value: score }) => (
|
|
score === null ? '-' : `${score.pointsEarned}/${score.pointsPossible}`
|
|
);
|
|
|
|
formatStatus = ({ value }) => (<StatusBadge status={value} />);
|
|
|
|
translate = (...args) => this.props.intl.formatMessage(...args);
|
|
|
|
handleViewAllResponsesClick(data) {
|
|
const getsubmissionUUID = (row) => row.original.submissionUUID;
|
|
const rows = data.selectedRows.length ? data.selectedRows : data.tableInstance.rows;
|
|
this.props.loadSelectionForReview(rows.map(getsubmissionUUID));
|
|
}
|
|
|
|
selectedBulkAction(selectedFlatRows) {
|
|
return {
|
|
buttonText: this.translate(
|
|
messages.viewSelectedResponses,
|
|
{ value: selectedFlatRows.length },
|
|
),
|
|
className: 'view-selected-responses-btn',
|
|
handleClick: this.handleViewAllResponsesClick,
|
|
variant: 'primary',
|
|
};
|
|
}
|
|
|
|
render() {
|
|
if (!this.props.listData.length) {
|
|
return null;
|
|
}
|
|
return (
|
|
<DataTable
|
|
isFilterable
|
|
FilterStatusComponent={FilterStatusComponent}
|
|
numBreakoutFilters={2}
|
|
defaultColumnValues={{ Filter: TextFilter }}
|
|
isSelectable
|
|
isSortable
|
|
isPaginated
|
|
itemCount={this.props.listData.length}
|
|
initialState={{ pageSize: 10, pageIndex: 0 }}
|
|
data={this.props.listData}
|
|
tableActions={[
|
|
{
|
|
buttonText: this.translate(messages.viewAllResponses),
|
|
handleClick: this.handleViewAllResponsesClick,
|
|
className: 'view-all-responses-btn',
|
|
variant: 'primary',
|
|
},
|
|
]}
|
|
bulkActions={[
|
|
this.selectedBulkAction,
|
|
]}
|
|
columns={[
|
|
{
|
|
Header: this.userLabel,
|
|
accessor: this.userAccessor,
|
|
},
|
|
{
|
|
Header: this.dateSubmittedLabel,
|
|
accessor: submissionFields.dateSubmitted,
|
|
Cell: this.formatDate,
|
|
disableFilters: true,
|
|
},
|
|
{
|
|
Header: this.translate(messages.grade),
|
|
accessor: submissionFields.score,
|
|
Cell: this.formatGrade,
|
|
disableFilters: true,
|
|
},
|
|
{
|
|
Header: this.translate(messages.gradingStatus),
|
|
accessor: submissionFields.gradingStatus,
|
|
Cell: this.formatStatus,
|
|
Filter: MultiSelectDropdownFilter,
|
|
filter: 'includesValue',
|
|
filterChoices: this.gradeStatusOptions,
|
|
},
|
|
]}
|
|
>
|
|
<DataTable.TableControlBar />
|
|
<DataTable.Table />
|
|
<DataTable.TableFooter />
|
|
</DataTable>
|
|
);
|
|
}
|
|
}
|
|
SubmissionsTable.defaultProps = {
|
|
listData: [],
|
|
};
|
|
SubmissionsTable.propTypes = {
|
|
// injected
|
|
intl: intlShape.isRequired,
|
|
// redux
|
|
isIndividual: PropTypes.bool.isRequired,
|
|
listData: PropTypes.arrayOf(PropTypes.shape({
|
|
username: PropTypes.string,
|
|
dateSubmitted: PropTypes.number,
|
|
gradingStatus: PropTypes.string,
|
|
score: PropTypes.shape({
|
|
pointsEarned: PropTypes.number,
|
|
pointsPossible: PropTypes.number,
|
|
}),
|
|
})),
|
|
loadSelectionForReview: PropTypes.func.isRequired,
|
|
};
|
|
|
|
export const mapStateToProps = (state) => ({
|
|
listData: selectors.submissions.listData(state),
|
|
isIndividual: selectors.app.ora.isIndividual(state),
|
|
});
|
|
|
|
export const mapDispatchToProps = {
|
|
loadSelectionForReview: thunkActions.grading.loadSelectionForReview,
|
|
};
|
|
|
|
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(SubmissionsTable));
|