Skip to content

Commit

Permalink
Merge pull request #221 from ReCodEx/warn-empty-refsol-note
Browse files Browse the repository at this point in the history
Adding warning and confirm query to submit ref. solution dialog to prevent empty submission descriptions
  • Loading branch information
Martin Kruliš authored Apr 26, 2018
2 parents 60ff17e + 14fa53c commit b13a7bc
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 158 deletions.
358 changes: 204 additions & 154 deletions src/components/Submissions/SubmitSolution/SubmitSolution.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { injectIntl, intlShape, defineMessages } from 'react-intl';
Expand All @@ -23,6 +23,8 @@ import {
} from '../../icons';
import UploadContainer from '../../../containers/UploadContainer';
import UsersNameContainer from '../../../containers/UsersNameContainer';
import Confirm from '../../forms/Confirm';

import { createGetUploadedFiles } from '../../../redux/selectors/upload';
import { hasEntryPoint } from '../../../redux/selectors/submission';

Expand All @@ -49,6 +51,16 @@ const commonMessages = defineMessages({
defaultMessage:
'Select the point of entry (bootstrap file of your application):'
},
emptyNoteWarning: {
id: 'app.submitSolution.emptyNoteWarning',
defaultMessage:
'The description is empty. Reference solutions are strongly encouraged to be labeled with relevant descriptions.'
},
emptyNoteSubmitConfirm: {
id: 'app.submitSolution.emptyNoteSubmitConfirm',
defaultMessage:
'The description is empty. Reference solutions are strongly encouraged to be labeled with relevant descriptions. Do you rellay wish to proceed with submit?'
},
resetForm: {
id: 'generic.reset',
defaultMessage: 'Reset'
Expand Down Expand Up @@ -99,168 +111,206 @@ const referenceSolutionMessages = defineMessages({
}
});

const SubmitSolution = ({
userId,
isOpen,
onClose,
onFilesChange,
reset,
uploadId,
canSubmit,
isSending,
isValidating,
hasFailed,
note = '',
attachedFiles,
presubmitEnvironments,
presubmitVariables,
selectedEnvironment,
changeRuntimeEnvironment,
selectedEntryPoint,
changeEntryPoint,
saveNote,
submitSolution,
isReferenceSolution,
messages,
intl: { formatMessage }
}) =>
<Modal show={isOpen} backdrop="static" onHide={onClose} bsSize="large">
<Modal.Header closeButton>
<Modal.Title>
{formatMessage(messages.title)}
</Modal.Title>
</Modal.Header>
<Modal.Body>
<p>
<UsersNameContainer userId={userId} />
</p>
class SubmitSolution extends Component {
_createSubmitButton = (btnProps = {}) => {
const { canSubmit, hasFailed, intl: { formatMessage } } = this.props;
return (
<Button
type="submit"
disabled={!canSubmit}
bsStyle={hasFailed ? 'danger' : canSubmit ? 'success' : 'default'}
className="btn-flat"
{...btnProps}
>
{hasFailed ? <WarningIcon gapRight /> : <SendIcon gapRight />}
{formatMessage(commonMessages.submitButton)}
</Button>
);
};

<Row>
<Col md={12} lg={6}>
<UploadContainer id={uploadId} onChange={onFilesChange} />
</Col>
<Col md={12} lg={6}>
<FormGroup>
<ControlLabel>
{formatMessage(commonMessages.runtimeEnvironment)}
</ControlLabel>
{isValidating
? <p>
<LoadingIcon gapRight />
{formatMessage(commonMessages.validating)}
</p>
: !presubmitEnvironments
? <p className="text-left callout callout-info">
{formatMessage(commonMessages.uploadFilesFirst)}
</p>
: presubmitEnvironments.length > 0
? <FormControl
onChange={e => changeRuntimeEnvironment(e.target.value)}
componentClass="select"
defaultValue={selectedEnvironment}
>
{presubmitEnvironments.map(rte =>
<option key={rte.id} value={rte.id}>
{rte.name}
</option>
)}
</FormControl>
: <p className="text-left callout callout-danger">
{formatMessage(commonMessages.noEnvironments)}
</p>}
</FormGroup>
createSubmitButton = () => {
const {
isReferenceSolution,
note,
submitSolution,
intl: { formatMessage }
} = this.props;
return isReferenceSolution && note.trim().length === 0
? <Confirm
id={'ref-solution-submit'}
onConfirmed={submitSolution}
question={formatMessage(commonMessages.emptyNoteSubmitConfirm)}
placement="top"
>
{this._createSubmitButton()}
</Confirm>
: this._createSubmitButton({
onClick: submitSolution
});
};

{Boolean(
!isValidating &&
presubmitVariables &&
presubmitVariables.length > 0 &&
attachedFiles &&
attachedFiles.length > 1 &&
hasEntryPoint(presubmitVariables, selectedEnvironment)
) &&
<FormGroup>
<ControlLabel>
{formatMessage(commonMessages.entryPoint)}
</ControlLabel>
<FormControl
onChange={e => changeEntryPoint(e.target.value)}
componentClass="select"
defaultValue={selectedEntryPoint}
>
{attachedFiles.map(item => item.name).sort().map(file =>
<option key={file} value={file}>
{file}
</option>
)}
</FormControl>
</FormGroup>}
render() {
const {
userId,
isOpen,
onClose,
onFilesChange,
reset,
uploadId,
canSubmit,
isSending,
isValidating,
hasFailed,
note = '',
attachedFiles,
presubmitEnvironments,
presubmitVariables,
selectedEnvironment,
changeRuntimeEnvironment,
selectedEntryPoint,
changeEntryPoint,
saveNote,
isReferenceSolution,
messages,
intl: { formatMessage }
} = this.props;

return (
<Modal show={isOpen} backdrop="static" onHide={onClose} bsSize="large">
<Modal.Header closeButton>
<Modal.Title>
{formatMessage(messages.title)}
</Modal.Title>
</Modal.Header>
<Modal.Body>
<p>
<UsersNameContainer userId={userId} />
</p>

<hr />
<Row>
<Col md={12} lg={6}>
<UploadContainer id={uploadId} onChange={onFilesChange} />
</Col>
<Col md={12} lg={6}>
<FormGroup>
<ControlLabel>
{formatMessage(commonMessages.runtimeEnvironment)}
</ControlLabel>
{isValidating
? <p>
<LoadingIcon gapRight />
{formatMessage(commonMessages.validating)}
</p>
: !presubmitEnvironments
? <p className="text-left callout callout-info">
{formatMessage(commonMessages.uploadFilesFirst)}
</p>
: presubmitEnvironments.length > 0
? <FormControl
onChange={e =>
changeRuntimeEnvironment(e.target.value)}
componentClass="select"
defaultValue={selectedEnvironment}
>
{presubmitEnvironments.map(rte =>
<option key={rte.id} value={rte.id}>
{rte.name}
</option>
)}
</FormControl>
: <p className="text-left callout callout-danger">
{formatMessage(commonMessages.noEnvironments)}
</p>}
</FormGroup>

<FormGroup>
<ControlLabel>
{formatMessage(messages.noteLabel)}
</ControlLabel>
<FormControl
onChange={e => saveNote(e.target.value)}
value={note}
type="text"
/>
</FormGroup>
</Col>
</Row>
{hasFailed &&
<p className="text-left callout callout-danger">
{formatMessage(commonMessages.submissionRejected)}
</p>}
</Modal.Body>
<Modal.Footer>
<div className="text-center">
{isSending &&
<Button
type="submit"
disabled={true}
bsStyle="success"
className="btn-flat"
>
<LoadingIcon gapRight />
{formatMessage(commonMessages.submitting)}
</Button>}
{Boolean(
!isValidating &&
presubmitVariables &&
presubmitVariables.length > 0 &&
attachedFiles &&
attachedFiles.length > 1 &&
hasEntryPoint(presubmitVariables, selectedEnvironment)
) &&
<FormGroup>
<ControlLabel>
{formatMessage(commonMessages.entryPoint)}
</ControlLabel>
<FormControl
onChange={e => changeEntryPoint(e.target.value)}
componentClass="select"
defaultValue={selectedEntryPoint}
>
{attachedFiles.map(item => item.name).sort().map(file =>
<option key={file} value={file}>
{file}
</option>
)}
</FormControl>
</FormGroup>}

{!isSending &&
<Button
type="submit"
disabled={!canSubmit}
bsStyle={hasFailed ? 'danger' : canSubmit ? 'success' : 'default'}
className="btn-flat"
onClick={submitSolution}
>
{hasFailed ? <WarningIcon gapRight /> : <SendIcon gapRight />}
{formatMessage(commonMessages.submitButton)}
</Button>}
<hr />

<Button bsStyle="default" className="btn-flat" onClick={reset}>
<DeleteIcon gapRight />
{formatMessage(commonMessages.resetForm)}
</Button>
<FormGroup>
<ControlLabel>
{formatMessage(messages.noteLabel)}
</ControlLabel>
<FormControl
onChange={e => saveNote(e.target.value)}
value={note}
type="text"
/>
</FormGroup>
{isReferenceSolution &&
note.trim().length === 0 &&
<p className="callout callout-danger">
{formatMessage(commonMessages.emptyNoteWarning)}
</p>}
</Col>
</Row>
{hasFailed &&
<p className="text-left callout callout-danger">
{formatMessage(commonMessages.submissionRejected)}
</p>}
</Modal.Body>
<Modal.Footer>
<div className="text-center">
{isSending &&
<Button
type="submit"
disabled={true}
bsStyle="success"
className="btn-flat"
>
<LoadingIcon gapRight />
{formatMessage(commonMessages.submitting)}
</Button>}

<Button bsStyle="default" className="btn-flat" onClick={onClose}>
<CloseIcon gapRight />
{formatMessage(commonMessages.closeForm)}
</Button>
</div>
<br />
<br />
{!isSending && this.createSubmitButton()}

{!canSubmit &&
<Well>
<HelpBlock className="text-left">
{formatMessage(commonMessages.instructions)}
</HelpBlock>
</Well>}
</Modal.Footer>
</Modal>;
<Button bsStyle="default" className="btn-flat" onClick={reset}>
<DeleteIcon gapRight />
{formatMessage(commonMessages.resetForm)}
</Button>

<Button bsStyle="default" className="btn-flat" onClick={onClose}>
<CloseIcon gapRight />
{formatMessage(commonMessages.closeForm)}
</Button>
</div>
<br />
<br />

{!canSubmit &&
<Well>
<HelpBlock className="text-left">
{formatMessage(commonMessages.instructions)}
</HelpBlock>
</Well>}
</Modal.Footer>
</Modal>
);
}
}
SubmitSolution.propTypes = {
userId: PropTypes.string.isRequired,
onClose: PropTypes.func.isRequired,
Expand Down
Loading

0 comments on commit b13a7bc

Please sign in to comment.