diff --git a/src/components/Buttons/PrimaryButton/PrimaryButton.module.scss b/src/components/Buttons/PrimaryButton/PrimaryButton.module.scss index f2a856c6..d14556cd 100644 --- a/src/components/Buttons/PrimaryButton/PrimaryButton.module.scss +++ b/src/components/Buttons/PrimaryButton/PrimaryButton.module.scss @@ -20,13 +20,28 @@ &.danger { background-color: $tc-red; + + &:disabled { + cursor: default; + background-color: $inactive; + } } &.info { background-color: $tc-blue-20; + + &:disabled { + cursor: default; + background-color: $inactive; + } } &.success { background-color: $tc-green-40; + + &:disabled { + cursor: default; + background-color: $inactive; + } } } diff --git a/src/components/Buttons/PrimaryButton/index.js b/src/components/Buttons/PrimaryButton/index.js index 48be4d1d..89c9a552 100644 --- a/src/components/Buttons/PrimaryButton/index.js +++ b/src/components/Buttons/PrimaryButton/index.js @@ -6,10 +6,10 @@ import cn from 'classnames' import styles from './PrimaryButton.module.scss' -const PrimaryButton = ({ type, text, link, onClick, submit }) => { +const PrimaryButton = ({ type, text, link, onClick, submit, disabled }) => { if (_.isEmpty(link)) { return ( - ) @@ -26,7 +26,8 @@ PrimaryButton.propTypes = { text: PropTypes.string.isRequired, link: PropTypes.string, onClick: PropTypes.func, - submit: PropTypes.bool + submit: PropTypes.bool, + disabled: PropTypes.bool } export default PrimaryButton diff --git a/src/components/ChallengeEditor/FinalDeliverables-Field/FinalDeliverables-Field.module.scss b/src/components/ChallengeEditor/FinalDeliverables-Field/FinalDeliverables-Field.module.scss index aa2f9e96..4dd15523 100644 --- a/src/components/ChallengeEditor/FinalDeliverables-Field/FinalDeliverables-Field.module.scss +++ b/src/components/ChallengeEditor/FinalDeliverables-Field/FinalDeliverables-Field.module.scss @@ -47,104 +47,55 @@ } } - .tcCheckbox { - @include tc-checkbox; - - .tc-checkbox-label { - @include roboto-light(); - - line-height: 17px; - font-weight: 300; - margin-left: 21px; - user-select: none; - cursor: pointer; - width: 195px; - font-size: 14px; - color: #3d3d3d; - } - - height: 18px; - width: 210px; + .fileTypeList { margin: 0; padding: 0; - vertical-align: bottom; - position: relative; - display: inline-block; - margin-bottom: 18px; - - input[type='checkbox'] { - display: none; - - &:checked ~ label { - background: $tc-blue-20; - } - - &:checked + label::after { - border-color: $white; - } - } - - label { - @include roboto-light(); - - line-height: 17px; - font-weight: 300; - cursor: pointer; - position: absolute; - display: inline-block; - width: 14px; - height: 14px; - top: 0; - left: 0; - border: none; - box-shadow: none; - background: $tc-gray-30; - transition: all 0.15s ease-in-out; - - &.readOnly { - cursor: auto; - } + } - &::after { - opacity: 0; - content: ''; - position: absolute; - width: 9px; - height: 5px; - background: transparent; - top: 2px; - left: 2px; - border-top: none; - border-right: none; - transform: rotate(-45deg); - transition: all 0.15s ease-in-out; - } + .fileTypeListEditable { - &:hover::after { - opacity: 0.3; - } - &:hover:read-only::after { - opacity: 0; - } + } - div { - margin-left: 24px; - width: 500px; - } - } + .fileTypeItem { + background-color: #2C95D7; + border-radius: 2px; + border: 1px solid #c9e6f2; + color: #ffffff; + display: inline-block; + font-size: 14px; + margin-right: 5px; + padding: 2px 30px 2px 5px; + position: relative; + vertical-align: top; } - .checkList { + .fileTypeDelete { + align-items: center; + background-color: #c6def1; + border: 0; + color: #2C95D7; + cursor: pointer; display: flex; - flex-direction: column; - margin-left: 30px; + border-radius: 50%; + font-size: 14px; + height: 16px; + justify-content: center; + position: absolute; + right: 5px; + top: 50%; + transform: translateY(-50%); + width: 16px; + + &:hover { + background-color: #fff; + } } form { display: flex; flex-direction: row; } - + .button { width: 137px; height: 40px; diff --git a/src/components/ChallengeEditor/FinalDeliverables-Field/index.js b/src/components/ChallengeEditor/FinalDeliverables-Field/index.js index df76eeb7..57ead390 100644 --- a/src/components/ChallengeEditor/FinalDeliverables-Field/index.js +++ b/src/components/ChallengeEditor/FinalDeliverables-Field/index.js @@ -17,12 +17,12 @@ class FinalDeliverablesField extends Component { } onChangeInput (value) { - this.setState({ newFileType: _.trim(value) }) + this.setState({ newFileType: value }) } onAddFileType (event) { if (!_.isEmpty(this.state.newFileType)) { - this.props.addFileType(this.state.newFileType) + this.props.addFileType(this.state.newFileType.trim()) this.setState({ newFileType: '' }) } @@ -31,7 +31,11 @@ class FinalDeliverablesField extends Component { } render () { - const { challenge, onUpdateCheckbox, readOnly } = this.props + const { challenge, readOnly, removeFileType } = this.props + const fileTypesMetadata = _.find(challenge.metadata, { name: 'fileTypes' }) + const fileTypes = (fileTypesMetadata && JSON.parse(fileTypesMetadata.value)) || [] + const isDuplicateValue = _.includes(fileTypes, this.state.newFileType.trim()) + return (
@@ -40,27 +44,18 @@ class FinalDeliverablesField extends Component {
-
- { - _.map(challenge.fileTypes, (type, index) => ( -
- onUpdateCheckbox(type.name, e.target.checked, 'fileTypes', index)} - readOnly={readOnly} - /> - -
- )) - } -
+ {!readOnly ? ( + + ) : ( + fileTypes.join(', ') + )}
{!readOnly && (
@@ -76,6 +71,7 @@ class FinalDeliverablesField extends Component {
@@ -93,8 +89,8 @@ FinalDeliverablesField.defaultProps = { FinalDeliverablesField.propTypes = { challenge: PropTypes.shape().isRequired, - onUpdateCheckbox: PropTypes.func.isRequired, addFileType: PropTypes.func.isRequired, + removeFileType: PropTypes.func.isRequired, readOnly: PropTypes.bool } diff --git a/src/components/ChallengeEditor/TextEditor-Field/index.js b/src/components/ChallengeEditor/TextEditor-Field/index.js index 74d2b57f..303b8968 100644 --- a/src/components/ChallengeEditor/TextEditor-Field/index.js +++ b/src/components/ChallengeEditor/TextEditor-Field/index.js @@ -29,6 +29,7 @@ class TextEditorField extends Component { challenge, onUpdateCheckbox, addFileType, + removeFileType, onUpdateDescription, onUpdateMultiSelect, shouldShowPrivateDescription, @@ -87,6 +88,7 @@ class TextEditorField extends Component { challenge={challenge} onUpdateCheckbox={onUpdateCheckbox} addFileType={addFileType} + removeFileType={removeFileType} readOnly={readOnly} /> -1) { + fileTypesMetadata = { ...newChallenge.metadata[fileTypesMetadataIndex] } + newChallenge.metadata[fileTypesMetadataIndex] = fileTypesMetadata + // if not yet, create an empty record in metadata + } else { + fileTypesMetadata = { name: 'fileTypes', value: '[]' } + newChallenge.metadata.push(fileTypesMetadata) + } + + // as values in metadata are always stored as string, we have to parse it, update and stringify again + const oldFileTypes = JSON.parse(fileTypesMetadata.value) + const newFileTypes = processValue(oldFileTypes) + fileTypesMetadata.value = JSON.stringify(newFileTypes) + this.setState({ challenge: newChallenge }) } + /** + * Add new file type + * @param {String} newFileType The new file type + */ + addFileType (newFileType) { + this.updateFileTypesMetadata((oldFileTypes) => { + const newFileTypes = [...oldFileTypes, newFileType] + + return newFileTypes + }) + } + + /** + * Remove file type + * @param {String} fileType file type + */ + removeFileType (fileType) { + this.updateFileTypesMetadata((oldFileTypes) => { + const newFileTypes = _.reject(oldFileTypes, (type) => type === fileType) + + return newFileTypes + }) + } + /** * Update Metadata * @param name Name of data @@ -1312,6 +1362,7 @@ class ChallengeEditor extends Component { challenge={challenge} onUpdateCheckbox={this.onUpdateCheckbox} addFileType={this.addFileType} + removeFileType={this.removeFileType} onUpdateInput={this.onUpdateInput} onUpdateDescription={this.onUpdateDescription} onUpdateMultiSelect={this.onUpdateMultiSelect}