Skip to content

Commit

Permalink
Student stats visible to students
Browse files Browse the repository at this point in the history
  • Loading branch information
SemaiCZE committed Feb 24, 2018
1 parent 3aa3110 commit 4b34ace
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 86 deletions.
25 changes: 7 additions & 18 deletions src/components/Groups/ResultsTable/ResultsTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,15 @@ import { Link } from 'react-router';
import { FormattedMessage } from 'react-intl';

import ResultsTableRow from './ResultsTableRow';
import LoadingResultsTableRow from './LoadingResultsTableRow';
import NoResultsAvailableRow from './NoResultsAvailableRow';
import withLinks from '../../../hoc/withLinks';
import ResourceRenderer from '../../helpers/ResourceRenderer';
import { LocalizedExerciseName } from '../../helpers/LocalizedNames';
import styles from './ResultsTable.less';

const ResultsTable = ({
assignments = List(),
users = [],
submissions,
stats,
links: { SUPERVISOR_STATS_URI_FACTORY }
}) => {
const assignmentsArray = assignments.sort(
Expand Down Expand Up @@ -53,21 +51,12 @@ const ResultsTable = ({
{users.length !== 0 &&
assignments.length !== 0 &&
users.map(user =>
<ResourceRenderer
<ResultsTableRow
key={user.id}
resource={Object.keys(submissions[user.id]).map(
key => submissions[user.id][key]
)}
loading={<LoadingResultsTableRow />}
>
{(...userSubmissions) =>
<ResultsTableRow
key={user.id}
userId={user.id}
assignmentsIds={assignmentsIds}
submissions={userSubmissions}
/>}
</ResourceRenderer>
userId={user.id}
assignmentsIds={assignmentsIds}
userStats={stats.find(stat => stat.userId === user.id)}
/>
)}
</tbody>
</Table>
Expand All @@ -77,7 +66,7 @@ const ResultsTable = ({
ResultsTable.propTypes = {
assignments: PropTypes.array.isRequired,
users: PropTypes.array.isRequired,
submissions: PropTypes.object.isRequired,
stats: PropTypes.array.isRequired,
links: PropTypes.object
};

Expand Down
42 changes: 19 additions & 23 deletions src/components/Groups/ResultsTable/ResultsTableRow.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,41 @@ import React from 'react';
import PropTypes from 'prop-types';
import UsersNameContainer from '../../../containers/UsersNameContainer';

const ResultsTableRow = ({ userId, assignmentsIds, submissions }) => {
var totalPoints = 0;
const ResultsTableRow = ({ userId, assignmentsIds, userStats }) => {
return (
<tr>
<td>
<UsersNameContainer userId={userId} />
</td>
{assignmentsIds.map(assignmentId => {
const submission = submissions
.filter(s => s !== null)
.filter(s => s.exerciseAssignmentId === assignmentId)[0];
const points =
submission &&
submission !== null &&
submission.lastSubmission.evaluation &&
Number.isInteger(submission.lastSubmission.evaluation.points)
? submission.lastSubmission.evaluation.points
: '-';
const bonusPoints =
submission && submission !== null ? submission.bonusPoints : 0;
totalPoints += points !== '-' ? points : 0;
totalPoints += bonusPoints;
const assignmentData =
userStats && userStats.assignments
? userStats.assignments.find(
assignment => assignment.id === assignmentId
)
: {};
return (
<td key={assignmentId}>
{points}
{bonusPoints > 0 &&
{assignmentData.points &&
Number.isInteger(assignmentData.points.gained)
? assignmentData.points.gained
: '-'}
{assignmentData.points &&
assignmentData.points.bonus > 0 &&
<span style={{ color: 'green' }}>
+{bonusPoints}
+{assignmentData.points.bonus}
</span>}
{bonusPoints < 0 &&
{assignmentData.points &&
assignmentData.points.bonus < 0 &&
<span style={{ color: 'red' }}>
{bonusPoints}
{assignmentData.points.bonus}
</span>}
</td>
);
})}
<td style={{ textAlign: 'right' }}>
<b>
{totalPoints}
{userStats && userStats.points ? userStats.points.gained : '-'}/{userStats && userStats.points ? userStats.points.total : '-'}
</b>
</td>
</tr>
Expand All @@ -50,7 +46,7 @@ const ResultsTableRow = ({ userId, assignmentsIds, submissions }) => {
ResultsTableRow.propTypes = {
userId: PropTypes.string.isRequired,
assignmentsIds: PropTypes.array.isRequired,
submissions: PropTypes.array.isRequired
userStats: PropTypes.object
};

export default ResultsTableRow;
28 changes: 28 additions & 0 deletions src/components/Groups/StudentsView/StudentsView.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@ import AssignmentsTable from '../../Assignments/Assignment/AssignmentsTable';
import StudentsListContainer from '../../../containers/StudentsListContainer';
import LeaveJoinGroupButtonContainer from '../../../containers/LeaveJoinGroupButtonContainer';
import { getLocalizedName } from '../../../helpers/getLocalizedData';
import ResourceRenderer from '../../helpers/ResourceRenderer';
import ResultsTableContainer from '../../../containers/ResultsTableContainer';

const StudentsView = ({
group,
statuses = [],
assignments,
bestSubmissions,
isAdmin = false,
users,
intl: { locale }
}) =>
<div>
Expand Down Expand Up @@ -78,12 +81,37 @@ const StudentsView = ({
</Box>
</Col>
</Row>
<Row>
<Col xs={12}>
<Box
title={
<FormattedMessage
id="app.group.spervisorsView.resultsTable"
defaultMessage="Results"
/>
}
isOpen
unlimitedHeight
noPadding
>
<ResourceRenderer resource={assignments}>
{(...assignments) =>
<ResultsTableContainer
groupId={group.id}
users={users}
assignments={assignments}
/>}
</ResourceRenderer>
</Box>
</Col>
</Row>
</div>;

StudentsView.propTypes = {
group: PropTypes.object.isRequired,
assignments: ImmutablePropTypes.list.isRequired,
statuses: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
users: PropTypes.array.isRequired,
isAdmin: PropTypes.bool,
bestSubmissions: PropTypes.object,
intl: PropTypes.shape({ locale: PropTypes.string.isRequired }).isRequired
Expand Down
21 changes: 0 additions & 21 deletions src/components/Groups/SupervisorsView/SupervisorsView.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import AddStudent from '../AddStudent';
import SearchExercise from '../SearchExercise';
import AdminAssignmentsTable from '../../Assignments/AdminAssignmentsTable';
import ExercisesSimpleList from '../../../components/Exercises/ExercisesSimpleList';
import ResultsTableContainer from '../../../containers/ResultsTableContainer';
import Button from '../../../components/widgets/FlatButton';
import { AddIcon, EditIcon, DeleteIcon } from '../../../components/icons';
import AssignExerciseButton from '../../../components/buttons/AssignExerciseButton';
Expand Down Expand Up @@ -45,26 +44,6 @@ const SupervisorsView = ({
</h3>
</Col>
</Row>
<Row>
<Col xs={12}>
<Box
title={
<FormattedMessage
id="app.group.spervisorsView.resultsTable"
defaultMessage="Results"
/>
}
isOpen
unlimitedHeight
noPadding
>
<ResourceRenderer resource={publicAssignments}>
{(...assignments) =>
<ResultsTableContainer users={users} assignments={assignments} />}
</ResourceRenderer>
</Box>
</Col>
</Row>
<Row>
<Col lg={6}>
<Box
Expand Down
44 changes: 21 additions & 23 deletions src/containers/ResultsTableContainer/ResultsTableContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,55 +2,53 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';

import ResourceRenderer from '../../components/helpers/ResourceRenderer';
import ResultsTable from '../../components/Groups/ResultsTable';
import { fetchBestSubmissions } from '../../redux/modules/groupResults';
import { getBestSubmissionsAssoc } from '../../redux/selectors/groupResults';
import { fetchGroupsStats } from '../../redux/modules/stats';
import { createGroupsStatsSelector } from '../../redux/selectors/stats';

class ResultsTableContainer extends Component {
componentWillMount() {
this.props.loadAsync();
}

componentWillReceiveProps(newProps) {
if (
this.props.users.length !== newProps.users.length ||
this.props.users.some((user, i) => user.id !== newProps.users[i].id)
) {
if (this.props.groupId !== newProps.groupId) {
this.props.loadAsync();
}
}

static loadAsync = ({ users, assignments }, dispatch) => {
assignments.map(assignment =>
dispatch(fetchBestSubmissions(assignment.id))
);
};
static loadAsync = ({ groupId }, dispatch) =>
dispatch(fetchGroupsStats(groupId));

render() {
const { users, assignments, submissions } = this.props;
const { users, assignments, stats } = this.props;
return (
<ResultsTable
users={users}
assignments={assignments}
submissions={submissions}
/>
<ResourceRenderer resource={stats}>
{groupStats =>
<ResultsTable
users={users}
assignments={assignments}
stats={groupStats}
/>}
</ResourceRenderer>
);
}
}

ResultsTableContainer.propTypes = {
users: PropTypes.array.isRequired,
assignments: PropTypes.array.isRequired,
submissions: PropTypes.object,
groupId: PropTypes.string.isRequired,
stats: PropTypes.object.isRequired,
loadAsync: PropTypes.func
};

export default connect(
(state, { users, assignments }) => ({
submissions: getBestSubmissionsAssoc(assignments, users)(state)
(state, { groupId }) => ({
stats: createGroupsStatsSelector(groupId)(state)
}),
(dispatch, { users, assignments }) => ({
loadAsync: () =>
ResultsTableContainer.loadAsync({ users, assignments }, dispatch)
(dispatch, { groupId }) => ({
loadAsync: () => ResultsTableContainer.loadAsync({ groupId }, dispatch)
})
)(ResultsTableContainer);
1 change: 1 addition & 0 deletions src/pages/Dashboard/Dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ class Dashboard extends Component {
</LinkContainer>
</p>
}
unlimitedHeight
>
<AssignmentsTable
userId={user.id}
Expand Down
1 change: 1 addition & 0 deletions src/pages/Group/Group.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ class Group extends Component {
assignments={publicAssignments}
bestSubmissions={bestSubmissions}
isAdmin={isAdmin || isSuperAdmin}
users={students}
/>}

<GroupDetail
Expand Down
2 changes: 1 addition & 1 deletion src/redux/modules/stats.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const { actions, reduceActions } = factory({
});

export const fetchGroupsStats = actions.fetchResource;
export const fetchGroupsStatsIfNeeded = actions.fetchOneIfNeeded;
export const fetchGroupsStatsIfNeeded = actions.fetchIfNeeded;

const reducer = handleActions(
Object.assign({}, reduceActions, {
Expand Down

0 comments on commit 4b34ace

Please sign in to comment.