Skip to content

Commit

Permalink
Display point stats in assignment overview
Browse files Browse the repository at this point in the history
Fixes #131
  • Loading branch information
SemaiCZE committed Dec 22, 2017
1 parent fd205cb commit 4bf586a
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -23,6 +24,7 @@ const AssignmentTableRow = ({
},
status,
userId,
bestSubmission,
links: {
ASSIGNMENT_DETAIL_URI_FACTORY,
ASSIGNMENT_DETAIL_SPECIFIC_USER_URI_FACTORY
Expand All @@ -48,6 +50,25 @@ const AssignmentTableRow = ({
<td>
{group}
</td>}
{bestSubmission &&
<td>
<ResourceRenderer resource={bestSubmission}>
{data =>
data.lastSubmission
? <span>
{data.lastSubmission.evaluation.points}
{data.bonusPoints > 0 &&
<span style={{ color: 'green' }}>
+{data.bonusPoints}
</span>}
{data.bonusPoints < 0 &&
<span style={{ color: 'red' }}>
{data.bonusPoints}
</span>}/{data.maxPoints}
</span>
: <span />}
</ResourceRenderer>
</td>}
<td>
<FormattedDate value={new Date(firstDeadline * 1000)} />
{', '}
Expand Down Expand Up @@ -76,6 +97,7 @@ AssignmentTableRow.propTypes = {
}),
status: PropTypes.string,
userId: PropTypes.string,
bestSubmission: PropTypes.object,
links: PropTypes.object
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
}) =>
<Table hover>
Expand All @@ -68,6 +82,13 @@ const AssignmentsTable = ({
defaultMessage="Group"
/>
</th>}
{displayPoints(bestSubmissions, assignments) &&
<th>
<FormattedMessage
id="app.assignments.points"
defaultMessage="Points"
/>
</th>}
<th>
<FormattedMessage
id="app.assignments.deadline"
Expand Down Expand Up @@ -99,6 +120,7 @@ const AssignmentsTable = ({
showGroup={showGroup}
status={statuses[assignment.id]}
locale={locale}
bestSubmission={bestSubmissions[assignment.id]}
/>
)}
</tbody>
Expand All @@ -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
};

Expand Down
3 changes: 3 additions & 0 deletions src/components/Groups/StudentsView/StudentsView.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const StudentsView = ({
group,
statuses = [],
assignments,
bestSubmissions,
isAdmin = false,
intl: { locale }
}) =>
Expand Down Expand Up @@ -47,6 +48,7 @@ const StudentsView = ({
assignments={assignments}
showGroup={false}
statuses={statuses}
bestSubmissions={bestSubmissions}
/>
</Box>
</Col>
Expand Down Expand Up @@ -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
};

Expand Down
15 changes: 14 additions & 1 deletion src/pages/Group/Group.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) =>
Expand Down Expand Up @@ -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()
])
),
Expand All @@ -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)) {
Expand Down Expand Up @@ -174,6 +184,7 @@ class Group extends Component {
publicAssignments = List(),
stats,
statuses,
bestSubmissions,
isStudent,
isAdmin,
isSuperAdmin,
Expand Down Expand Up @@ -215,13 +226,13 @@ class Group extends Component {
</Button>
</LinkContainer>
</p>}

{(isStudent || isSupervisor || isAdmin || isSuperAdmin) &&
<StudentsView
group={data}
stats={stats}
statuses={statuses}
assignments={publicAssignments}
bestSubmissions={bestSubmissions}
isAdmin={isAdmin || isSuperAdmin}
/>}

Expand Down Expand Up @@ -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,
Expand All @@ -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),
Expand Down
21 changes: 7 additions & 14 deletions src/redux/modules/groupResults.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
);
Expand Down
18 changes: 16 additions & 2 deletions src/redux/selectors/groupResults.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { createSelector } from 'reselect';
import { loggedInUserIdSelector } from './auth';

export const getGroupResults = state => state.groupResults;
export const getBestSubmission = (userId, assignmentId) =>
createSelector(
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
);
Expand All @@ -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;
}
);

0 comments on commit 4bf586a

Please sign in to comment.