diff --git a/src/components/Assignments/Assignment/AssignmentSync/AssignmentSync.js b/src/components/Assignments/Assignment/AssignmentSync/AssignmentSync.js index 4e6678118..a81b17b40 100644 --- a/src/components/Assignments/Assignment/AssignmentSync/AssignmentSync.js +++ b/src/components/Assignments/Assignment/AssignmentSync/AssignmentSync.js @@ -81,7 +81,7 @@ const getSyncMessages = syncInfo => { const res = []; for (const field in syncMessages) { if (!syncInfo[field]) { - console.log('Field ' + field + ' not present.'); + // console.log('Field ' + field + ' not present.'); continue; } diff --git a/src/components/Assignments/Assignment/AssignmentTableRow/AssignmentTableRow.js b/src/components/Assignments/Assignment/AssignmentTableRow/AssignmentTableRow.js index 5b0eb4c6c..fc6dd2c2e 100644 --- a/src/components/Assignments/Assignment/AssignmentTableRow/AssignmentTableRow.js +++ b/src/components/Assignments/Assignment/AssignmentTableRow/AssignmentTableRow.js @@ -4,6 +4,7 @@ import { Link } from 'react-router'; import AssignmentStatusIcon from '../AssignmentStatusIcon/AssignmentStatusIcon'; import { FormattedDate, FormattedTime } from 'react-intl'; +import ResourceRenderer from '../../../helpers/ResourceRenderer'; import withLinks from '../../../../hoc/withLinks'; import { LocalizedExerciseName } from '../../../helpers/LocalizedNames'; import { MaybeBonusAssignmentIcon } from '../../../icons'; @@ -23,6 +24,7 @@ const AssignmentTableRow = ({ }, status, userId, + bestSubmission, links: { ASSIGNMENT_DETAIL_URI_FACTORY, ASSIGNMENT_DETAIL_SPECIFIC_USER_URI_FACTORY @@ -48,6 +50,25 @@ const AssignmentTableRow = ({ {group} } + {bestSubmission && + + + {data => + data.lastSubmission + ? + {data.lastSubmission.evaluation.points} + {data.bonusPoints > 0 && + + +{data.bonusPoints} + } + {data.bonusPoints < 0 && + + {data.bonusPoints} + }/{data.maxPoints} + + : } + + } {', '} @@ -76,6 +97,7 @@ AssignmentTableRow.propTypes = { }), status: PropTypes.string, userId: PropTypes.string, + bestSubmission: PropTypes.object, links: PropTypes.object }; diff --git a/src/components/Assignments/Assignment/AssignmentsTable/AssignmentsTable.js b/src/components/Assignments/Assignment/AssignmentsTable/AssignmentsTable.js index 6959343dd..96a72d918 100644 --- a/src/components/Assignments/Assignment/AssignmentsTable/AssignmentsTable.js +++ b/src/components/Assignments/Assignment/AssignmentsTable/AssignmentsTable.js @@ -44,11 +44,25 @@ const compareAssignments = (a, b) => { } }; +const displayPoints = (bestSubmissions, assignments) => { + const assignmentIds = assignments + .filter(isReady) + .map(getJsData) + .map(assignment => assignment.id); + return Object.keys(bestSubmissions) + .filter(key => assignmentIds.indexOf(key) >= 0) + .reduce((acc, key) => { + acc = acc || bestSubmissions[key]; + return acc; + }, false); +}; + const AssignmentsTable = ({ assignments = List(), statuses = [], showGroup = true, userId = null, + bestSubmissions = {}, intl: { locale } }) => @@ -68,6 +82,13 @@ const AssignmentsTable = ({ defaultMessage="Group" /> } + {displayPoints(bestSubmissions, assignments) && + } @@ -109,6 +131,7 @@ AssignmentsTable.propTypes = { showGroup: PropTypes.bool, statuses: PropTypes.oneOfType([PropTypes.object, PropTypes.array]), userId: PropTypes.string, + bestSubmissions: PropTypes.object, intl: PropTypes.shape({ locale: PropTypes.string.isRequired }).isRequired }; diff --git a/src/components/Groups/StudentsView/StudentsView.js b/src/components/Groups/StudentsView/StudentsView.js index 563c89f1e..61d0bab82 100644 --- a/src/components/Groups/StudentsView/StudentsView.js +++ b/src/components/Groups/StudentsView/StudentsView.js @@ -14,6 +14,7 @@ const StudentsView = ({ group, statuses = [], assignments, + bestSubmissions, isAdmin = false, intl: { locale } }) => @@ -47,6 +48,7 @@ const StudentsView = ({ assignments={assignments} showGroup={false} statuses={statuses} + bestSubmissions={bestSubmissions} /> @@ -83,6 +85,7 @@ StudentsView.propTypes = { assignments: ImmutablePropTypes.list.isRequired, statuses: PropTypes.oneOfType([PropTypes.object, PropTypes.array]), isAdmin: PropTypes.bool, + bestSubmissions: PropTypes.object, intl: PropTypes.shape({ locale: PropTypes.string.isRequired }).isRequired }; diff --git a/src/pages/Group/Group.js b/src/pages/Group/Group.js index f4eb80114..a1022c291 100644 --- a/src/pages/Group/Group.js +++ b/src/pages/Group/Group.js @@ -62,6 +62,8 @@ import { getStatusesForLoggedUser } from '../../redux/selectors/stats'; import { getLocalizedName } from '../../helpers/getLocalizedData'; import withLinks from '../../hoc/withLinks'; import { isReady } from '../../redux/helpers/resourceManager/index'; +import { fetchBestSubmission } from '../../redux/modules/groupResults'; +import { getBestSubmissionsForLoggedInUser } from '../../redux/selectors/groupResults'; class Group extends Component { static isAdminOrSupervisorOf = (group, userId) => @@ -89,6 +91,13 @@ class Group extends Component { dispatch(fetchStudents(groupId)), dispatch(fetchGroupsStats(groupId)) ]) + : Promise.resolve(), + group.students.indexOf(userId) >= 0 + ? Promise.all( + group.assignments.all.map(assignmentId => + dispatch(fetchBestSubmission(userId, assignmentId)) + ) + ) : Promise.resolve() ]) ), @@ -105,6 +114,7 @@ class Group extends Component { if (groupId !== newProps.params.groupId) { newProps.loadAsync(newProps.userId, newProps.isSuperAdmin); + return; } if (isReady(this.props.group) && isReady(newProps.group)) { @@ -174,6 +184,7 @@ class Group extends Component { publicAssignments = List(), stats, statuses, + bestSubmissions, isStudent, isAdmin, isSuperAdmin, @@ -215,13 +226,13 @@ class Group extends Component {

} - {(isStudent || isSupervisor || isAdmin || isSuperAdmin) && } @@ -287,6 +298,7 @@ Group.propTypes = { loadAsync: PropTypes.func, stats: PropTypes.object, statuses: PropTypes.oneOfType([PropTypes.object, PropTypes.array]), + bestSubmissions: PropTypes.object, assignExercise: PropTypes.func.isRequired, createGroupExercise: PropTypes.func.isRequired, push: PropTypes.func.isRequired, @@ -311,6 +323,7 @@ const mapStateToProps = (state, { params: { groupId } }) => { allAssignments: groupsAllAssignmentsSelector(state, groupId), groupExercises: getExercisesForGroup(state, groupId), statuses: getStatusesForLoggedUser(state, groupId), + bestSubmissions: getBestSubmissionsForLoggedInUser(state), supervisors: supervisorsOfGroupSelector(state, groupId), students: studentsOfGroupSelector(state, groupId), isStudent: isStudentOf(userId, groupId)(state), diff --git a/src/redux/modules/groupResults.js b/src/redux/modules/groupResults.js index 56b277821..73756bdbd 100644 --- a/src/redux/modules/groupResults.js +++ b/src/redux/modules/groupResults.js @@ -52,21 +52,14 @@ const reducer = handleActions( [additionalActionTypes.BEST_SUBMISSION_FULFILLED]: ( state, - { payload = {}, meta: { assignmentId } } + { payload = {}, meta: { assignmentId, userId } } ) => - Object.keys(payload).reduce( - (state, userId) => - state - .setIn( - ['resources', assignmentId, userId, 'data'], - fromJS(payload[userId]) - ) - .setIn( - ['resources', assignmentId, userId, 'state'], - resourceStatus.FULFILLED - ), - state - ) + state + .setIn(['resources', assignmentId, userId, 'data'], fromJS(payload)) + .setIn( + ['resources', assignmentId, userId, 'state'], + resourceStatus.FULFILLED + ) }), initialState ); diff --git a/src/redux/selectors/groupResults.js b/src/redux/selectors/groupResults.js index 78b9df8db..6ff10785f 100644 --- a/src/redux/selectors/groupResults.js +++ b/src/redux/selectors/groupResults.js @@ -1,4 +1,5 @@ import { createSelector } from 'reselect'; +import { loggedInUserIdSelector } from './auth'; export const getGroupResults = state => state.groupResults; export const getBestSubmission = (userId, assignmentId) => @@ -6,8 +7,8 @@ export const getBestSubmission = (userId, assignmentId) => getGroupResults, groupResults => groupResults && - groupResults.getIn(['resources', assignmentId]) !== null && - groupResults.getIn(['resources', assignmentId, userId]) !== null + groupResults.getIn(['resources', assignmentId]) !== null && + groupResults.getIn(['resources', assignmentId, userId]) !== null ? groupResults.getIn(['resources', assignmentId, userId]) : null ); @@ -29,3 +30,16 @@ export const getBestSubmissionsAssoc = (assignments, users) => return submissions; }); + +export const getBestSubmissionsForLoggedInUser = createSelector( + [getGroupResults, loggedInUserIdSelector], + (groupResults, userId) => { + const submissions = {}; + groupResults + .get('resources') + .forEach( + (value, assignmentId) => (submissions[assignmentId] = value.get(userId)) + ); + return submissions; + } +);
+ + )}