diff --git a/src/containers/ListView/SubmissionsTable.jsx b/src/containers/ListView/SubmissionsTable.jsx
index 5b89b51..fe4f2a6 100644
--- a/src/containers/ListView/SubmissionsTable.jsx
+++ b/src/containers/ListView/SubmissionsTable.jsx
@@ -9,7 +9,7 @@ import {
} from '@edx/paragon';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
-import { gradingStatuses } from 'data/services/lms/constants';
+import { gradingStatuses, submissionFields } from 'data/services/lms/constants';
import lmsMessages from 'data/services/lms/messages';
import { selectors, thunkActions } from 'data/redux';
@@ -35,6 +35,22 @@ export class SubmissionsTable extends React.Component {
}));
}
+ 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();
@@ -94,24 +110,24 @@ export class SubmissionsTable extends React.Component {
]}
columns={[
{
- Header: this.translate(messages.username),
- accessor: 'username',
+ Header: this.userLabel,
+ accessor: this.userAccessor,
},
{
- Header: this.translate(messages.learnerSubmissionDate),
- accessor: 'dateSubmitted',
+ Header: this.dateSubmittedLabel,
+ accessor: submissionFields.dateSubmitted,
Cell: this.formatDate,
disableFilters: true,
},
{
Header: this.translate(messages.grade),
- accessor: 'score',
+ accessor: submissionFields.score,
Cell: this.formatGrade,
disableFilters: true,
},
{
Header: this.translate(messages.gradingStatus),
- accessor: 'gradingStatus',
+ accessor: submissionFields.gradingStatus,
Cell: this.formatStatus,
Filter: MultiSelectDropdownFilter,
filter: 'includesValue',
@@ -134,6 +150,7 @@ SubmissionsTable.propTypes = {
// injected
intl: intlShape.isRequired,
// redux
+ isIndividual: PropTypes.bool.isRequired,
listData: PropTypes.arrayOf(PropTypes.shape({
username: PropTypes.string,
dateSubmitted: PropTypes.number,
@@ -148,6 +165,7 @@ SubmissionsTable.propTypes = {
export const mapStateToProps = (state) => ({
listData: selectors.submissions.listData(state),
+ isIndividual: selectors.app.ora.isIndividual(state),
});
export const mapDispatchToProps = {
diff --git a/src/containers/ListView/SubmissionsTable.test.jsx b/src/containers/ListView/SubmissionsTable.test.jsx
index 2610dad..003974a 100644
--- a/src/containers/ListView/SubmissionsTable.test.jsx
+++ b/src/containers/ListView/SubmissionsTable.test.jsx
@@ -8,7 +8,7 @@ import {
} from '@edx/paragon';
import { selectors, thunkActions } from 'data/redux';
-import { gradingStatuses as statuses } from 'data/services/lms/constants';
+import { gradingStatuses as statuses, submissionFields } from 'data/services/lms/constants';
import StatusBadge from 'components/StatusBadge';
import { formatMessage } from 'testUtils';
@@ -21,6 +21,11 @@ import {
jest.mock('data/redux', () => ({
selectors: {
+ app: {
+ ora: {
+ isIndividual: (...args) => ({ isIndividual: args }),
+ },
+ },
submissions: {
listData: (...args) => ({ listData: args }),
},
@@ -35,38 +40,71 @@ jest.mock('data/redux', () => ({
let el;
jest.useFakeTimers('modern');
+const individualData = [
+ {
+ username: 'username-1',
+ dateSubmitted: 16131215154955,
+ gradingStatus: statuses.ungraded,
+ score: {
+ pointsEarned: 1,
+ pointsPossible: 10,
+ },
+ },
+ {
+ username: 'username-2',
+ dateSubmitted: 16131225154955,
+ gradingStatus: statuses.graded,
+ score: {
+ pointsEarned: 2,
+ pointsPossible: 10,
+ },
+ },
+ {
+ username: 'username-3',
+ dateSubmitted: 16131215250955,
+ gradingStatus: statuses.inProgress,
+ score: {
+ pointsEarned: 3,
+ pointsPossible: 10,
+ },
+ },
+];
+
+const teamData = [
+ {
+ teamName: 'teamName-1',
+ dateSubmitted: 16131215154955,
+ gradingStatus: statuses.ungraded,
+ score: {
+ pointsEarned: 1,
+ pointsPossible: 10,
+ },
+ },
+ {
+ teamName: 'teamName-2',
+ dateSubmitted: 16131225154955,
+ gradingStatus: statuses.graded,
+ score: {
+ pointsEarned: 2,
+ pointsPossible: 10,
+ },
+ },
+ {
+ teamName: 'teamName-3',
+ dateSubmitted: 16131215250955,
+ gradingStatus: statuses.inProgress,
+ score: {
+ pointsEarned: 3,
+ pointsPossible: 10,
+ },
+ },
+];
+
describe('SubmissionsTable component', () => {
describe('component', () => {
const props = {
- listData: [
- {
- username: 'username-1',
- dateSubmitted: 16131215154955,
- gradingStatus: statuses.ungraded,
- score: {
- pointsEarned: 1,
- pointsPossible: 10,
- },
- },
- {
- username: 'username-2',
- dateSubmitted: 16131225154955,
- gradingStatus: statuses.graded,
- score: {
- pointsEarned: 2,
- pointsPossible: 10,
- },
- },
- {
- username: 'username-3',
- dateSubmitted: 16131215250955,
- gradingStatus: statuses.inProgress,
- score: {
- pointsEarned: 3,
- pointsPossible: 10,
- },
- },
- ],
+ isIndividual: true,
+ listData: [...individualData],
};
beforeEach(() => {
props.loadSelectionForReview = jest.fn();
@@ -95,6 +133,10 @@ describe('SubmissionsTable component', () => {
test('snapshot: happy path', () => {
expect(el.instance().render()).toMatchSnapshot();
});
+ test('snapshot: team happy path', () => {
+ el.setProps({ isIndividual: false, listData: [...teamData] });
+ expect(el.instance().render()).toMatchSnapshot();
+ });
});
describe('DataTable', () => {
let table;
@@ -118,7 +160,7 @@ describe('SubmissionsTable component', () => {
test('bulkActions linked to selectedBulkAction', () => {
expect(tableProps.bulkActions).toEqual([el.instance().selectedBulkAction]);
});
- describe('columns', () => {
+ describe('individual columns', () => {
let columns;
beforeEach(() => {
columns = tableProps.columns;
@@ -126,13 +168,13 @@ describe('SubmissionsTable component', () => {
test('username column', () => {
expect(columns[0]).toEqual({
Header: messages.username.defaultMessage,
- accessor: 'username',
+ accessor: submissionFields.username,
});
});
test('submission date column', () => {
expect(columns[1]).toEqual({
Header: messages.learnerSubmissionDate.defaultMessage,
- accessor: 'dateSubmitted',
+ accessor: submissionFields.dateSubmitted,
Cell: el.instance().formatDate,
disableFilters: true,
});
@@ -140,7 +182,7 @@ describe('SubmissionsTable component', () => {
test('grade column', () => {
expect(columns[2]).toEqual({
Header: messages.grade.defaultMessage,
- accessor: 'score',
+ accessor: submissionFields.score,
Cell: el.instance().formatGrade,
disableFilters: true,
});
@@ -148,7 +190,46 @@ describe('SubmissionsTable component', () => {
test('grading status column', () => {
expect(columns[3]).toEqual({
Header: messages.gradingStatus.defaultMessage,
- accessor: 'gradingStatus',
+ accessor: submissionFields.gradingStatus,
+ Cell: el.instance().formatStatus,
+ Filter: MultiSelectDropdownFilter,
+ filter: 'includesValue',
+ filterChoices: el.instance().gradeStatusOptions,
+ });
+ });
+ });
+ describe('team columns', () => {
+ let columns;
+ beforeEach(() => {
+ el.setProps({ isIndividual: false, listData: [...teamData] });
+ columns = el.find(DataTable).props().columns;
+ });
+ test('teamName column', () => {
+ expect(columns[0]).toEqual({
+ Header: messages.teamName.defaultMessage,
+ accessor: submissionFields.teamName,
+ });
+ });
+ test('submission date column', () => {
+ expect(columns[1]).toEqual({
+ Header: messages.teamSubmissionDate.defaultMessage,
+ accessor: submissionFields.dateSubmitted,
+ Cell: el.instance().formatDate,
+ disableFilters: true,
+ });
+ });
+ test('grade column', () => {
+ expect(columns[2]).toEqual({
+ Header: messages.grade.defaultMessage,
+ accessor: submissionFields.score,
+ Cell: el.instance().formatGrade,
+ disableFilters: true,
+ });
+ });
+ test('grading status column', () => {
+ expect(columns[3]).toEqual({
+ Header: messages.gradingStatus.defaultMessage,
+ accessor: submissionFields.gradingStatus,
Cell: el.instance().formatStatus,
Filter: MultiSelectDropdownFilter,
filter: 'includesValue',
diff --git a/src/containers/ListView/__snapshots__/SubmissionsTable.test.jsx.snap b/src/containers/ListView/__snapshots__/SubmissionsTable.test.jsx.snap
index 5c373df..5bd942a 100644
--- a/src/containers/ListView/__snapshots__/SubmissionsTable.test.jsx.snap
+++ b/src/containers/ListView/__snapshots__/SubmissionsTable.test.jsx.snap
@@ -121,3 +121,123 @@ exports[`SubmissionsTable component component render tests snapshots snapshot: h
`;
+
+exports[`SubmissionsTable component component render tests snapshots snapshot: team happy path 1`] = `
+
+
+
+
+
+
+`;
diff --git a/src/containers/ReviewActions/__snapshots__/index.test.jsx.snap b/src/containers/ReviewActions/__snapshots__/index.test.jsx.snap
index 2331a6e..0d7a7f5 100644
--- a/src/containers/ReviewActions/__snapshots__/index.test.jsx.snap
+++ b/src/containers/ReviewActions/__snapshots__/index.test.jsx.snap
@@ -11,7 +11,7 @@ exports[`ReviewActions component component snapshot: do not show rubric 1`] = `
- test-username
+ test-userDisplay
- test-username
+ test-userDisplay
- test-username
+ test-userDisplay
(
- {username}
+ {userDisplay}
{ gradingStatus && (
)}
@@ -59,7 +59,7 @@ ReviewActions.defaultProps = {
};
ReviewActions.propTypes = {
gradingStatus: PropTypes.string,
- username: PropTypes.string.isRequired,
+ userDisplay: PropTypes.string.isRequired,
score: PropTypes.shape({
pointsEarned: PropTypes.number,
pointsPossible: PropTypes.number,
@@ -70,7 +70,7 @@ ReviewActions.propTypes = {
};
export const mapStateToProps = (state) => ({
- username: selectors.grading.selected.username(state),
+ userDisplay: selectors.grading.selected.userDisplay(state),
gradingStatus: selectors.grading.selected.gradingStatus(state),
score: selectors.grading.selected.score(state),
showRubric: selectors.app.showRubric(state),
diff --git a/src/containers/ReviewActions/index.test.jsx b/src/containers/ReviewActions/index.test.jsx
index b2e8023..2999828 100644
--- a/src/containers/ReviewActions/index.test.jsx
+++ b/src/containers/ReviewActions/index.test.jsx
@@ -13,7 +13,7 @@ jest.mock('data/redux/grading/selectors', () => ({
selected: {
gradingStatus: (state) => ({ gradingStatus: state }),
score: (state) => ({ score: state }),
- username: (state) => ({ username: state }),
+ userDisplay: (state) => ({ userDisplay: state }),
},
}));
jest.mock('data/redux/requests/selectors', () => ({
@@ -27,7 +27,7 @@ describe('ReviewActions component', () => {
describe('component', () => {
const props = {
gradingStatus: 'grading-status',
- username: 'test-username',
+ userDisplay: 'test-userDisplay',
showRubric: false,
score: { pointsEarned: 3, pointsPossible: 10 },
};
@@ -54,8 +54,8 @@ describe('ReviewActions component', () => {
const requestKey = RequestKeys.fetchSubmission;
expect(mapped.isLoaded).toEqual(selectors.requests.isCompleted(testState, { requestKey }));
});
- test('username loads from grading.selected.username', () => {
- expect(mapped.username).toEqual(selectors.grading.selected.username(testState));
+ test('userDisplay loads from grading.selected.userDisplay', () => {
+ expect(mapped.userDisplay).toEqual(selectors.grading.selected.userDisplay(testState));
});
test('gradingStatus loads from grading.selected.gradingStatus', () => {
expect(mapped.gradingStatus).toEqual(selectors.grading.selected.gradingStatus(testState));
diff --git a/src/data/redux/app/selectors.js b/src/data/redux/app/selectors.js
index a6c3a4a..100e4d5 100644
--- a/src/data/redux/app/selectors.js
+++ b/src/data/redux/app/selectors.js
@@ -1,6 +1,6 @@
import { createSelector } from 'reselect';
-import { feedbackRequirement } from 'data/services/lms/constants';
+import { feedbackRequirement, oraTypes } from 'data/services/lms/constants';
import { StrictDict } from 'utils';
@@ -46,6 +46,11 @@ export const ora = {
* @return {string} - file upload response config
*/
fileUploadResponseConfig: oraMetadataSelector(data => data.fileUploadResponseConfig),
+ /**
+ * Returns true iff the ORA is an individual submission ora (vs team)
+ * @return {bool} - is the ORA an individual ORA?
+ */
+ isIndividual: oraMetadataSelector(data => data.type === oraTypes.individual),
};
/**
diff --git a/src/data/redux/grading/selectors.js b/src/data/redux/grading/selectors.js
index 070a577..12f1b00 100644
--- a/src/data/redux/grading/selectors.js
+++ b/src/data/redux/grading/selectors.js
@@ -113,6 +113,20 @@ selected.username = createSelector(
(staticData) => staticData.username,
);
+selected.teamName = createSelector(
+ [module.selected.staticData],
+ (staticData) => staticData.teamName,
+);
+
+selected.userDisplay = createSelector(
+ [
+ appSelectors.ora.isIndividual,
+ module.selected.username,
+ module.selected.teamName,
+ ],
+ (isIndividual, username, teamName) => (isIndividual ? username : teamName),
+);
+
/***********************************
* Selected Submission - Grade Data
***********************************/
diff --git a/src/data/services/lms/constants.js b/src/data/services/lms/constants.js
index 00c1bf3..76f7657 100644
--- a/src/data/services/lms/constants.js
+++ b/src/data/services/lms/constants.js
@@ -34,3 +34,16 @@ export const paramKeys = StrictDict({
oraLocation: 'oraLocation',
submissionUUID: 'submissionUUID',
});
+
+export const oraTypes = StrictDict({
+ team: 'team',
+ individual: 'individual',
+});
+
+export const submissionFields = StrictDict({
+ dateSubmitted: 'dateSubmitted',
+ gradingStatus: 'gradingStatus',
+ score: 'score',
+ teamName: 'teamName',
+ username: 'username',
+});