Skip to content

Commit

Permalink
Display which users a choice conflicts with on the finalisation screen
Browse files Browse the repository at this point in the history
Previously, if a conflicting choice was made, the two offending rows
would turn BRIGHT RED, but no other feedback was visible -- since the
other row would frequently be scrolled off the screen, this is not
exactly the most helpful way the application could tell the user that
something is wrong ("you did something wrong, but I'm not going to tell
you what it is").

Now, the name of the user(s) with which a choice conflicts is/are
displayed on the right-hand side of the table. That space is reserved
even if there is currently no conflict, since having the table jump
around underneath you if you choose a conflicting project is even worse
than the existing behaviour!

See #14.
  • Loading branch information
sersorrel committed Aug 28, 2019
1 parent d930983 commit 77fe312
Showing 1 changed file with 36 additions and 19 deletions.
55 changes: 36 additions & 19 deletions src/components/choice_editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
*/


import React, {Component} from 'react';
import React, {Component, Fragment} from 'react';
import { connect } from 'react-redux';
import {DropdownButton, MenuItem} from 'react-bootstrap';
import ClassNames from 'classnames';
Expand Down Expand Up @@ -75,30 +75,37 @@ class ChoiceEditor extends Component {
this.props.onClick(studentID, {type, id: parseInt(id, 10)});
}


// Produces an object mapping user IDs to lists of conflicting
// users. If a user's choice does not conflict, it will not be
// present in the keys of the returned object.
invalidChoices() {
return Object.keys(this.props.students).filter(userID => {
return Object.keys(this.props.students).reduce((obj, userID) => {
const userOption = this.props.choices[userID];
if (!userOption) {
return false;
return obj;
}
if (userOption.type === "user") {
return false;
return obj;
}
return Object.keys(this.props.students).some(otherUserID => {
const conflictingUsers = Object.keys(this.props.students).map(otherUserID => {
if (otherUserID === userID) {
return false;
return null;
}
const otherUserOption = this.props.choices[otherUserID];
if (!otherUserOption) {
return false;
return null;
}
if (otherUserOption.type === "user") {
return false;
return null;
}
return userOption.id === otherUserOption.id;
});
});
if (userOption.id !== otherUserOption.id) {
return null;
}
return otherUserID;
}).filter(x => x != null);
obj[userID] = conflictingUsers;
return obj;
}, {});
}

renderSaveButtons(submitDisabled, saveDisabled) {
Expand Down Expand Up @@ -182,14 +189,15 @@ class ChoiceEditor extends Component {
const [id, userAll] = kv;
const user = userAll.data;
const projectIDs = this.getUserChoices(user);
const conflicts = invalidUsers[id] || [];

return (
<div className={ClassNames("row", "striped", {"invalid": invalidUsers.includes(id)})} key={id}>
<div className="col-xs-3">{user.name}</div>
<div className={ClassNames("row", "striped", {"invalid": conflicts.length})} key={id}>
<div className="col-xs-3 col-lg-2">{user.name}</div>
{this.props.showPriority && (
<div className="col-xs-1">{user.priority}</div>
)}
<div className="col-xs-8">
<div className="col-xs-5 col-lg-6">
<ol>
{projectIDs.map((projectID, i) => {
const title = projectID != null ? this.getProjectTitle(projectID) : "(No choice)";
Expand All @@ -216,16 +224,25 @@ class ChoiceEditor extends Component {
</ol>
{showButtons && this.renderDropdowns(id)}
</div>
<div className="col-xs-3">
{
conflicts.length ?
<Fragment>Choice conflicts with {conflicts.map(uid =>
this.props.users[uid].data.name
).join(", ")}</Fragment>
: null
}
</div>
</div>
);
});
}

render() {
const showButtons = Boolean(this.props.choices);
const invalidUsers = showButtons? this.invalidChoices(): [];
const invalidUsers = showButtons? this.invalidChoices(): {};
return (
<div className="container">
<div className="container">
<div className="row">
<div className="col-xs-3">Student</div>
{this.props.showPriority && (
Expand All @@ -236,8 +253,8 @@ class ChoiceEditor extends Component {
{this.renderStudentChoices(invalidUsers)}

{showButtons && this.renderSaveButtons(
invalidUsers.length || Object.keys(this.props.choices).length < Object.keys(this.props.students).length,
Boolean(invalidUsers.length)
Object.keys(invalidUsers).length || Object.keys(this.props.choices).length < Object.keys(this.props.students).length,
Boolean(Object.keys(invalidUsers).length)
)}
</div>
);
Expand Down

0 comments on commit 77fe312

Please sign in to comment.