Skip to content

Commit

Permalink
Merge pull request #172 from ReCodEx/broken-flag
Browse files Browse the repository at this point in the history
Reflect exercise.isBroken flag in the UI.
  • Loading branch information
Martin Kruliš committed Jan 26, 2018
2 parents 591e2a7 + 3d671a6 commit 1d41072
Show file tree
Hide file tree
Showing 13 changed files with 196 additions and 79 deletions.
13 changes: 11 additions & 2 deletions src/components/Exercises/ExercisesListItem/ExercisesListItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Link } from 'react-router';

import withLinks from '../../../hoc/withLinks';
import { LocalizedExerciseName } from '../../helpers/LocalizedNames';
import { MaybeLockedExerciseIcon } from '../../icons';
import { ExercisePrefixIcons } from '../../icons';

const ExercisesListItem = ({
id,
Expand All @@ -20,6 +20,8 @@ const ExercisesListItem = ({
localizedTexts,
createdAt,
isLocked,
isBroken,
validationError,
createActions,
locale,
links: { EXERCISE_URI_FACTORY }
Expand All @@ -29,7 +31,12 @@ const ExercisesListItem = ({
<Icon name="code" />
</td>
<td>
<MaybeLockedExerciseIcon id={id} isLocked={isLocked} />
<ExercisePrefixIcons
id={id}
isLocked={isLocked}
isBroken={isBroken}
validationError={validationError}
/>
<strong>
<Link to={EXERCISE_URI_FACTORY(id)}>
<LocalizedExerciseName entity={{ name, localizedTexts }} />
Expand Down Expand Up @@ -74,6 +81,8 @@ ExercisesListItem.propTypes = {
difficulty: PropTypes.string.isRequired,
createdAt: PropTypes.number.isRequired,
isLocked: PropTypes.bool.isRequired,
isBroken: PropTypes.bool.isRequired,
validationError: PropTypes.string,
localizedTexts: PropTypes.array.isRequired,
createActions: PropTypes.func,
locale: PropTypes.string.isRequired,
Expand Down
13 changes: 11 additions & 2 deletions src/components/Exercises/ExercisesName/ExercisesName.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,25 @@ import { Link } from 'react-router';
import withLinks from '../../../hoc/withLinks';
import { LocalizedExerciseName } from '../../helpers/LocalizedNames';

import { MaybeLockedExerciseIcon } from '../../icons';
import { ExercisePrefixIcons } from '../../icons';

const ExercisesName = ({
id,
name,
localizedTexts,
isLocked,
isBroken,
validationError,
noLink,
links: { EXERCISE_URI_FACTORY }
}) =>
<span>
<MaybeLockedExerciseIcon id={id} isLocked={isLocked} />
<ExercisePrefixIcons
id={id}
isLocked={isLocked}
isBroken={isBroken}
validationError={validationError}
/>
{noLink
? <span>
<LocalizedExerciseName entity={{ name, localizedTexts }} />
Expand All @@ -31,6 +38,8 @@ ExercisesName.propTypes = {
name: PropTypes.string.isRequired,
localizedTexts: PropTypes.array.isRequired,
isLocked: PropTypes.bool.isRequired,
isBroken: PropTypes.bool.isRequired,
validationError: PropTypes.string,
noLink: PropTypes.bool,
links: PropTypes.object
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,29 @@ import { Link } from 'react-router';

import withLinks from '../../../hoc/withLinks';
import { LocalizedExerciseName } from '../../helpers/LocalizedNames';
import { MaybeLockedExerciseIcon } from '../../icons';
import { ExercisePrefixIcons } from '../../icons';

const ExercisesSimpleListItem = ({
id,
name,
difficulty,
authorId,
isLocked,
isBroken,
validationError,
localizedTexts,
createActions,
locale,
links: { EXERCISE_URI_FACTORY }
}) =>
<tr>
<td>
<MaybeLockedExerciseIcon id={id} isLocked={isLocked} />
<ExercisePrefixIcons
id={id}
isLocked={isLocked}
isBroken={isBroken}
validationError={validationError}
/>
<strong>
<Link to={EXERCISE_URI_FACTORY(id)}>
<LocalizedExerciseName entity={{ name, localizedTexts }} />
Expand All @@ -36,7 +43,7 @@ const ExercisesSimpleListItem = ({
</td>
{createActions &&
<td className="text-right">
{createActions(id, isLocked)}
{createActions(id, isLocked, isBroken)}
</td>}
</tr>;

Expand All @@ -46,6 +53,8 @@ ExercisesSimpleListItem.propTypes = {
name: PropTypes.string.isRequired,
difficulty: PropTypes.string.isRequired,
isLocked: PropTypes.bool.isRequired,
isBroken: PropTypes.bool.isRequired,
validationError: PropTypes.string,
localizedTexts: PropTypes.array.isRequired,
createActions: PropTypes.func,
locale: PropTypes.string.isRequired,
Expand Down
3 changes: 2 additions & 1 deletion src/components/Groups/SupervisorsView/SupervisorsView.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,11 @@ const SupervisorsView = ({
{(...exercises) =>
<ExercisesSimpleList
exercises={exercises}
createActions={(exerciseId, isLocked) =>
createActions={(exerciseId, isLocked, isBroken) =>
<div>
<AssignExerciseButton
isLocked={isLocked}
isBroken={isBroken}
assignExercise={() => assignExercise(exerciseId)}
/>
<LinkContainer to={EXERCISE_EDIT_URI_FACTORY(exerciseId)}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,30 @@
import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import Icon from 'react-fontawesome';
import Button from '../../widgets/FlatButton';
import { SendIcon, InfoIcon } from '../../../components/icons';

const AssignExerciseButton = ({ isLocked, assignExercise, ...props }) => {
if (isLocked) {
const AssignExerciseButton = ({
isLocked,
isBroken,
assignExercise,
...props
}) => {
if (isLocked || isBroken) {
return (
<Button bsSize="xs" className="btn-flat" disabled={true} {...props}>
<InfoIcon />
{isBroken ? <Icon name="medkit" /> : <InfoIcon />}
{' '}
<FormattedMessage
id="app.assignExerciseButton.isLocked"
defaultMessage="Locked"
/>
{isBroken
? <FormattedMessage
id="app.assignExerciseButton.isBroken"
defaultMessage="Broken"
/>
: <FormattedMessage
id="app.assignExerciseButton.isLocked"
defaultMessage="Locked"
/>}
</Button>
);
} else {
Expand All @@ -32,6 +43,7 @@ const AssignExerciseButton = ({ isLocked, assignExercise, ...props }) => {

AssignExerciseButton.propTypes = {
isLocked: PropTypes.bool.isRequired,
isBroken: PropTypes.bool.isRequired,
assignExercise: PropTypes.func.isRequired
};

Expand Down
51 changes: 51 additions & 0 deletions src/components/icons/ExercisePrefixIcons.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import Icon from 'react-fontawesome';
import { OverlayTrigger, Tooltip } from 'react-bootstrap';

const ExercisePrefixIcons = ({ id, isLocked, isBroken, ...props }) =>
<span>
{isLocked &&
<span>
<OverlayTrigger
placement="right"
overlay={
<Tooltip id={id}>
<FormattedMessage
id="app.ExercisePrefixIcons.isLocked"
defaultMessage="Exercise is locked by the author and cannot be assigned."
/>
</Tooltip>
}
>
<Icon {...props} name="lock" className="text-warning" />
</OverlayTrigger>
&nbsp;&nbsp;
</span>}
{isBroken &&
<span>
<OverlayTrigger
placement="right"
overlay={
<Tooltip id={id}>
<FormattedMessage
id="app.exercise.isBroken"
defaultMessage="Exercise configuration is incorrect and needs fixing"
/>
</Tooltip>
}
>
<Icon {...props} name="medkit" className="text-danger" />
</OverlayTrigger>
&nbsp;&nbsp;
</span>}
</span>;

ExercisePrefixIcons.propTypes = {
id: PropTypes.any.isRequired,
isLocked: PropTypes.bool.isRequired,
isBroken: PropTypes.bool.isRequired
};

export default ExercisePrefixIcons;
32 changes: 0 additions & 32 deletions src/components/icons/MaybeLockedExerciseIcon.js

This file was deleted.

2 changes: 1 addition & 1 deletion src/components/icons/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ export { default as SettingsIcon } from './SettingsIcon';
export {
default as MaybeBonusAssignmentIcon
} from './MaybeBonusAssignmentIcon';
export { default as MaybeLockedExerciseIcon } from './MaybeLockedExerciseIcon';
export { default as ExercisePrefixIcons } from './ExercisePrefixIcons';
export { default as CopyIcon } from './CopyIcon';
export { default as LocalIcon } from './LocalIcon';
3 changes: 3 additions & 0 deletions src/locales/cs.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"app.EditSimpleLimitsForm.validation.NaN": "Given value is not a number.",
"app.EditSimpleLimitsForm.validation.tooHigh": "Given value exceeds the recommended maximum ({max}).",
"app.EditSimpleLimitsForm.validation.tooLow": "Given value is below the recommended minimum ({min}).",
"app.ExercisePrefixIcons.isLocked": "Exercise is locked by author and cannot be assigned",
"app.acceptSolution.accepted": "Zrušit jako finální",
"app.acceptSolution.notAccepted": "Akceptovat jako finální",
"app.addLicence.addLicenceTitle": "Přidat novou licenci",
Expand Down Expand Up @@ -32,6 +33,7 @@
"app.adminAssignmentsTable.noAssignments": "Nejsou dostupné žádné úlohy.",
"app.adminAssignmentsTableRow.edit": "Upravit",
"app.adminAssignmentsTableRow.loading": "Načítají se zadané úlohy ...",
"app.assignExerciseButton.isBroken": "Broken",
"app.assignExerciseButton.isLocked": "Locked",
"app.assignemntStatusIcon.evaluationFailed": "Žádné řesení nebylo správně vyhodnoceno.",
"app.assignemntStatusIcon.failed": "Žádné správné řešení nebylo zatím odevzdáno.",
Expand Down Expand Up @@ -486,6 +488,7 @@
"app.exercise.forked": "Duplikováno z:",
"app.exercise.groups": "Groups:",
"app.exercise.groupsBox": "Skupiny",
"app.exercise.isBroken": "Exercise configuration is incorrect and needs fixing",
"app.exercise.isLocked": "Is locked:",
"app.exercise.isPublic": "Is public:",
"app.exercise.noReferenceSolutions": "Nyní zde nejsou žádná referenční řešení pro tuto úlohu.",
Expand Down
3 changes: 3 additions & 0 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"app.EditSimpleLimitsForm.validation.NaN": "Given value is not a number.",
"app.EditSimpleLimitsForm.validation.tooHigh": "Given value exceeds the recommended maximum ({max}).",
"app.EditSimpleLimitsForm.validation.tooLow": "Given value is below the recommended minimum ({min}).",
"app.ExercisePrefixIcons.isLocked": "Exercise is locked by author and cannot be assigned",
"app.acceptSolution.accepted": "Revoke as Final",
"app.acceptSolution.notAccepted": "Accept as Final",
"app.addLicence.addLicenceTitle": "Add new licence",
Expand Down Expand Up @@ -32,6 +33,7 @@
"app.adminAssignmentsTable.noAssignments": "There are no assignments.",
"app.adminAssignmentsTableRow.edit": "Edit",
"app.adminAssignmentsTableRow.loading": "Loading assignments ...",
"app.assignExerciseButton.isBroken": "Broken",
"app.assignExerciseButton.isLocked": "Locked",
"app.assignemntStatusIcon.evaluationFailed": "No solution was evaluated correctly by ReCodEx.",
"app.assignemntStatusIcon.failed": "No correct solution was submitted yet.",
Expand Down Expand Up @@ -486,6 +488,7 @@
"app.exercise.forked": "Forked from:",
"app.exercise.groups": "Groups:",
"app.exercise.groupsBox": "Groups",
"app.exercise.isBroken": "Exercise configuration is incorrect and needs fixing",
"app.exercise.isLocked": "Is locked:",
"app.exercise.isPublic": "Is public:",
"app.exercise.noReferenceSolutions": "There are no reference solutions for this exercise yet.",
Expand Down
16 changes: 16 additions & 0 deletions src/pages/EditExercise/EditExercise.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Row, Col } from 'react-bootstrap';
import { connect } from 'react-redux';
import { push } from 'react-router-redux';
import { reset, getFormValues } from 'redux-form';
import Icon from 'react-fontawesome';

import Page from '../../components/layout/Page';
import Box from '../../components/widgets/Box';
Expand Down Expand Up @@ -88,6 +89,21 @@ class EditExercise extends Component {
>
{exercise =>
<div>
{exercise.isBroken &&
<Row>
<Col sm={12}>
<div className="alert alert-warning">
<h4>
<Icon name="medkit" />&nbsp;&nbsp;
<FormattedMessage
id="app.exercise.isBroken"
defaultMessage="Exercise configuration is incorrect and needs fixing"
/>
</h4>
{exercise.validationError}
</div>
</Col>
</Row>}
<Row>
<Col lg={6}>
<EditExerciseForm
Expand Down
16 changes: 16 additions & 0 deletions src/pages/EditExerciseSimpleConfig/EditExerciseSimpleConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { FormattedMessage, injectIntl } from 'react-intl';
import { Row, Col } from 'react-bootstrap';
import { connect } from 'react-redux';
import { defaultMemoize } from 'reselect';
import Icon from 'react-fontawesome';

import Page from '../../components/layout/Page';
import Box from '../../components/widgets/Box';
Expand Down Expand Up @@ -236,6 +237,21 @@ class EditExerciseSimpleConfig extends Component {
pipelines // pipelines are returned as a whole array (so they can be cached properly)
) =>
<div>
{exercise.isBroken &&
<Row>
<Col sm={12}>
<div className="alert alert-warning">
<h4>
<Icon name="medkit" />&nbsp;&nbsp;
<FormattedMessage
id="app.exercise.isBroken"
defaultMessage="Exercise configuration is incorrect and needs fixing"
/>
</h4>
{exercise.validationError}
</div>
</Col>
</Row>}
<Row>
<Col lg={6}>
<Box
Expand Down
Loading

0 comments on commit 1d41072

Please sign in to comment.