Skip to content

Commit

Permalink
Merge pull request #155 from ReCodEx/fixes
Browse files Browse the repository at this point in the history
Fixes of small UI bugs, loading errors, etc.
  • Loading branch information
SemaiCZE committed Dec 27, 2017
2 parents 1864790 + 4bf586a commit b28baf9
Show file tree
Hide file tree
Showing 11 changed files with 130 additions and 37 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
19 changes: 10 additions & 9 deletions src/components/Users/SupervisorsList/SupervisorsList.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,16 @@ const SupervisorsList = ({
}) =>
<Table hover>
<tbody>
{users.map(user =>
<SupervisorsListItem
key={user.id}
{...user}
groupId={groupId}
isAdmin={isAdmin}
primaryAdminsIds={primaryAdminsIds}
/>
)}
{isLoaded &&
users.map(user =>
<SupervisorsListItem
key={user.id}
{...user}
groupId={groupId}
isAdmin={isAdmin}
primaryAdminsIds={primaryAdminsIds}
/>
)}

{users.length === 0 &&
isLoaded &&
Expand Down
8 changes: 2 additions & 6 deletions src/components/Users/UsersList/UsersList.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,8 @@ const UsersList = ({ users = [], createActions, intl, ...rest }) =>
const bName = b.name.lastName + ' ' + b.name.firstName;
return aName.localeCompare(bName, intl.locale);
})
.map(user =>
<UsersListItem
id={user.id}
createActions={createActions}
key={user.id}
/>
.map((user, i) =>
<UsersListItem id={user.id} createActions={createActions} key={i} />
)}

{users.length === 0 &&
Expand Down
11 changes: 11 additions & 0 deletions src/containers/SisIntegrationContainer/SisIntegrationContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ class SisIntegrationContainer extends Component {
defaultMessage="Name"
/>
</th>
<th>
<FormattedMessage
id="app.sisIntegration.courseId"
defaultMessage="Course ID"
/>
</th>
<th>
<FormattedMessage
id="app.sisIntegration.groupAdmins"
Expand All @@ -108,6 +114,11 @@ class SisIntegrationContainer extends Component {
<td>
{getLocalizedName(group, locale)}
</td>
<td>
<code>
{group.sisCode}
</code>
</td>
<td>
{group.primaryAdminsIds.map(id =>
<UsersNameContainer
Expand Down
35 changes: 31 additions & 4 deletions src/pages/Group/Group.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
fetchInstanceGroupsIfNeeded,
fetchSubgroups
} from '../../redux/modules/groups';
import { fetchGroupsStatsIfNeeded } from '../../redux/modules/stats';
import { fetchGroupsStats } from '../../redux/modules/stats';
import { fetchSupervisors, fetchStudents } from '../../redux/modules/users';
import {
fetchAssignmentsForGroup,
Expand Down Expand Up @@ -61,6 +61,9 @@ 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 All @@ -86,8 +89,15 @@ class Group extends Component {
? Promise.all([
dispatch(fetchAssignmentsForGroup(groupId)),
dispatch(fetchStudents(groupId)),
dispatch(fetchGroupsStatsIfNeeded(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 @@ -104,6 +114,18 @@ class Group extends Component {

if (groupId !== newProps.params.groupId) {
newProps.loadAsync(newProps.userId, newProps.isSuperAdmin);
return;
}

if (isReady(this.props.group) && isReady(newProps.group)) {
const thisData = this.props.group.toJS().data;
const newData = newProps.group.toJS().data;
if (thisData.supervisors.length !== newData.supervisors.length) {
newProps.refetchSupervisors();
}
if (thisData.students.length !== newData.students.length) {
newProps.loadAsync(newProps.userId, newProps.isSuperAdmin);
}
}
}

Expand Down Expand Up @@ -162,6 +184,7 @@ class Group extends Component {
publicAssignments = List(),
stats,
statuses,
bestSubmissions,
isStudent,
isAdmin,
isSuperAdmin,
Expand Down Expand Up @@ -203,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 @@ -275,9 +298,11 @@ 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,
refetchSupervisors: PropTypes.func.isRequired,
links: PropTypes.object,
intl: PropTypes.shape({ locale: PropTypes.string.isRequired }).isRequired
};
Expand All @@ -298,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 All @@ -322,7 +348,8 @@ const mapDispatchToProps = (dispatch, { params }) => ({
dispatch(assignExercise(params.groupId, exerciseId)),
createGroupExercise: () =>
dispatch(createExercise({ groupId: params.groupId })),
push: url => dispatch(push(url))
push: url => dispatch(push(url)),
refetchSupervisors: () => dispatch(fetchSupervisors(params.groupId))
});

export default withLinks(
Expand Down
5 changes: 4 additions & 1 deletion src/pages/ReferenceSolution/ReferenceSolution.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,10 @@ class ReferenceSolution extends Component {
<Button
bsStyle="success"
className="btn-flat"
onClick={evaluateReferenceSolution}
onClick={() =>
evaluateReferenceSolution().then(
refreshSolutionEvaluations
)}
>
<SendIcon />{' '}
<FormattedMessage
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 b28baf9

Please sign in to comment.