diff --git a/src/components/Exercises/AttachedFilesTable/AdditionalFilesTableHeaderRow.js b/src/components/Exercises/AttachedFilesTable/AdditionalFilesTableHeaderRow.js index 411a3edfd..ddec80849 100644 --- a/src/components/Exercises/AttachedFilesTable/AdditionalFilesTableHeaderRow.js +++ b/src/components/Exercises/AttachedFilesTable/AdditionalFilesTableHeaderRow.js @@ -1,7 +1,7 @@ import React from 'react'; import { FormattedMessage } from 'react-intl'; -const AdditionalFilesTableHeaderRow = () => ( +const AdditionalFilesTableHeaderRow = () => ( defaultMessage="Uploaded at" /> - -); + + ; export default AdditionalFilesTableHeaderRow; diff --git a/src/components/Exercises/AttachedFilesTable/AdditionalFilesTableRow.js b/src/components/Exercises/AttachedFilesTable/AdditionalFilesTableRow.js index 0d68c8ebf..c21e5632b 100644 --- a/src/components/Exercises/AttachedFilesTable/AdditionalFilesTableRow.js +++ b/src/components/Exercises/AttachedFilesTable/AdditionalFilesTableRow.js @@ -1,38 +1,68 @@ import React from 'react'; import PropTypes from 'prop-types'; import prettyBytes from 'pretty-bytes'; -import { FormattedDate, FormattedTime } from 'react-intl'; +import { FormattedDate, FormattedTime, FormattedMessage } from 'react-intl'; import withLinks from '../../../hoc/withLinks'; +import { Button } from 'react-bootstrap'; +import Confirm from '../../../components/forms/Confirm'; +import { DeleteIcon } from '../../../components/icons'; const AdditionalFilesTableRow = ({ id, name, size, uploadedAt, + removeFile, links: { DOWNLOAD } -}) => ( +}) => - {name} + + {name} + {DOWNLOAD(id)} - {prettyBytes(size)} + + {prettyBytes(size)} +   - -); + + {removeFile && + removeFile(id)} + question={ + + } + className="pull-right" + > + + } + + ; AdditionalFilesTableRow.propTypes = { id: PropTypes.string.isRequired, name: PropTypes.string.isRequired, size: PropTypes.number.isRequired, uploadedAt: PropTypes.number.isRequired, - links: PropTypes.object.isRequired + links: PropTypes.object.isRequired, + removeFile: PropTypes.func }; export default withLinks(AdditionalFilesTableRow); diff --git a/src/components/Exercises/AttachedFilesTable/AttachedFilesTable.js b/src/components/Exercises/AttachedFilesTable/AttachedFilesTable.js index adf22c4a8..33571e5e9 100644 --- a/src/components/Exercises/AttachedFilesTable/AttachedFilesTable.js +++ b/src/components/Exercises/AttachedFilesTable/AttachedFilesTable.js @@ -24,6 +24,8 @@ const AttachedFilesTable = ({ canSubmit, newFiles, addFiles, + removeFile, + downloadFile, uploadId, HeaderComponent, RowComponent @@ -61,7 +63,14 @@ const AttachedFilesTable = ({ {attachments .sort((a, b) => a.name.localeCompare(b.name)) - .map((data, i) => )} + .map((data, i) => + + )} } {attachments.length === 0 && @@ -93,6 +102,8 @@ AttachedFilesTable.propTypes = { canSubmit: PropTypes.bool, newFiles: ImmutablePropTypes.list, addFiles: PropTypes.func, + removeFile: PropTypes.func, + downloadFile: PropTypes.func, HeaderComponent: PropTypes.func.isRequired, RowComponent: PropTypes.func.isRequired }; diff --git a/src/components/Exercises/AttachedFilesTable/SupplementaryFilesTableRow.js b/src/components/Exercises/AttachedFilesTable/SupplementaryFilesTableRow.js index 9ebe711a7..8035f17ca 100644 --- a/src/components/Exercises/AttachedFilesTable/SupplementaryFilesTableRow.js +++ b/src/components/Exercises/AttachedFilesTable/SupplementaryFilesTableRow.js @@ -1,13 +1,10 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; import prettyBytes from 'pretty-bytes'; import { FormattedDate, FormattedTime, FormattedMessage } from 'react-intl'; import { Button } from 'react-bootstrap'; import Confirm from '../../../components/forms/Confirm'; import { DeleteIcon } from '../../../components/icons'; -import { downloadSupplementaryFile } from '../../../redux/modules/files'; -import { removeSupplementaryFile } from '../../../redux/modules/supplementaryFiles'; const SupplementaryFilesTableRow = ({ id, @@ -16,13 +13,17 @@ const SupplementaryFilesTableRow = ({ size, uploadedAt, downloadFile, - removeSupplementaryFile + removeFile }) => - - {name} - + {downloadFile + ? downloadFile(e, id)}> + {name} + + : + {name} + } {prettyBytes(size)} @@ -33,25 +34,26 @@ const SupplementaryFilesTableRow = ({ - removeSupplementaryFile(id)} - question={ - - } - className="pull-right" - > - - + {removeFile && + removeFile(id)} + question={ + + } + className="pull-right" + > + + } ; @@ -61,17 +63,8 @@ SupplementaryFilesTableRow.propTypes = { hashName: PropTypes.string.isRequired, size: PropTypes.number.isRequired, uploadedAt: PropTypes.number.isRequired, - downloadFile: PropTypes.func.isRequired, - removeSupplementaryFile: PropTypes.func.isRequired + downloadFile: PropTypes.func, + removeFile: PropTypes.func }; -export default connect( - (state, props) => ({}), - (dispatch, { id }) => ({ - downloadFile: e => { - e.preventDefault(); - dispatch(downloadSupplementaryFile(id)); - }, - removeSupplementaryFile: fileId => dispatch(removeSupplementaryFile(fileId)) - }) -)(SupplementaryFilesTableRow); +export default SupplementaryFilesTableRow; diff --git a/src/components/buttons/DeleteButton/index.js b/src/components/buttons/DeleteButton/index.js index 781ca4fb6..9f8239be3 100644 --- a/src/components/buttons/DeleteButton/index.js +++ b/src/components/buttons/DeleteButton/index.js @@ -2,3 +2,4 @@ export default from './DeleteButton'; export { default as DeletingButton } from './DeletingButton'; export { default as DeletedButton } from './DeletedButton'; export { default as DeletingFailedButton } from './DeletingFailedButton'; +export { default as ConfirmDeleteButton } from './ConfirmDeleteButton'; diff --git a/src/containers/AdditionalExerciseFilesTableContainer/AdditionalExerciseFilesTableContainer.js b/src/containers/AdditionalExerciseFilesTableContainer/AdditionalExerciseFilesTableContainer.js index 751f17d96..510e20810 100644 --- a/src/containers/AdditionalExerciseFilesTableContainer/AdditionalExerciseFilesTableContainer.js +++ b/src/containers/AdditionalExerciseFilesTableContainer/AdditionalExerciseFilesTableContainer.js @@ -12,24 +12,25 @@ import { import { fetchAdditionalExerciseFiles, - addAdditionalExerciseFiles + addAdditionalExerciseFiles, + removeAdditionalExerciseFile } from '../../redux/modules/additionalExerciseFiles'; -import { - createGetAdditionalExerciseFiles -} from '../../redux/selectors/additionalExerciseFiles'; +import { createGetAdditionalExerciseFiles } from '../../redux/selectors/additionalExerciseFiles'; const AdditionalExerciseFilesTableContainer = ({ exercise, additionalExerciseFiles, loadFiles, - addFiles -}) => ( + addFiles, + removeFile +}) => -); + />; AdditionalExerciseFilesTableContainer.propTypes = { exercise: PropTypes.shape({ @@ -54,7 +54,8 @@ AdditionalExerciseFilesTableContainer.propTypes = { }).isRequired, additionalExerciseFiles: ImmutablePropTypes.map, loadFiles: PropTypes.func.isRequired, - addFiles: PropTypes.func.isRequired + addFiles: PropTypes.func.isRequired, + removeFile: PropTypes.func.isRequired }; export default connect( @@ -68,6 +69,7 @@ export default connect( }, (dispatch, { exercise }) => ({ loadFiles: () => dispatch(fetchAdditionalExerciseFiles(exercise.id)), - addFiles: files => dispatch(addAdditionalExerciseFiles(exercise.id, files)) + addFiles: files => dispatch(addAdditionalExerciseFiles(exercise.id, files)), + removeFile: id => dispatch(removeAdditionalExerciseFile(exercise.id, id)) }) )(AdditionalExerciseFilesTableContainer); diff --git a/src/containers/SupplementaryFilesTableContainer/SupplementaryFilesTableContainer.js b/src/containers/SupplementaryFilesTableContainer/SupplementaryFilesTableContainer.js index 09ddc5fff..870595d01 100644 --- a/src/containers/SupplementaryFilesTableContainer/SupplementaryFilesTableContainer.js +++ b/src/containers/SupplementaryFilesTableContainer/SupplementaryFilesTableContainer.js @@ -12,24 +12,28 @@ import { import { fetchSupplementaryFilesForExercise, - addSupplementaryFiles + addSupplementaryFiles, + removeSupplementaryFile } from '../../redux/modules/supplementaryFiles'; +import { downloadSupplementaryFile } from '../../redux/modules/files'; -import { - createGetSupplementaryFiles -} from '../../redux/selectors/supplementaryFiles'; +import { createGetSupplementaryFiles } from '../../redux/selectors/supplementaryFiles'; const SupplementaryFilesTableContainer = ({ exercise, supplementaryFiles, loadFiles, - addFiles -}) => ( + addFiles, + removeFile, + downloadFile +}) => -); + />; SupplementaryFilesTableContainer.propTypes = { exercise: PropTypes.shape({ @@ -54,7 +57,9 @@ SupplementaryFilesTableContainer.propTypes = { }).isRequired, supplementaryFiles: ImmutablePropTypes.map, loadFiles: PropTypes.func.isRequired, - addFiles: PropTypes.func.isRequired + addFiles: PropTypes.func.isRequired, + removeFile: PropTypes.func.isRequired, + downloadFile: PropTypes.func.isRequired }; export default connect( @@ -68,6 +73,11 @@ export default connect( }, (dispatch, { exercise }) => ({ loadFiles: () => dispatch(fetchSupplementaryFilesForExercise(exercise.id)), - addFiles: files => dispatch(addSupplementaryFiles(exercise.id, files)) + addFiles: files => dispatch(addSupplementaryFiles(exercise.id, files)), + removeFile: id => dispatch(removeSupplementaryFile(exercise.id, id)), + downloadFile: (event, id) => { + event.preventDefault(); + dispatch(downloadSupplementaryFile(id)); + } }) )(SupplementaryFilesTableContainer); diff --git a/src/redux/modules/additionalExerciseFiles.js b/src/redux/modules/additionalExerciseFiles.js index 6fc997f31..05353554c 100644 --- a/src/redux/modules/additionalExerciseFiles.js +++ b/src/redux/modules/additionalExerciseFiles.js @@ -17,7 +17,9 @@ export const actionTypes = { ADD_FILES: 'recodex/additionalExerciseFiles/ADD_FILES', ADD_FILES_PENDING: 'recodex/additionalExerciseFiles/ADD_FILES_PENDING', ADD_FILES_FULFILLED: 'recodex/additionalExerciseFiles/ADD_FILES_FULFILLED', - ADD_FILES_FAILED: 'recodex/additionalExerciseFiles/ADD_FILES_REJECTED' + ADD_FILES_FAILED: 'recodex/additionalExerciseFiles/ADD_FILES_REJECTED', + REMOVE_FILE: 'recodex/additionalExerciseFiles/REMOVE_FILE', + REMOVE_FILE_FULFILLED: 'recodex/additionalExerciseFiles/REMOVE_FILE_FULFILLED' }; export const fetchAdditionalExerciseFiles = exerciseId => @@ -42,6 +44,14 @@ export const addAdditionalExerciseFiles = (exerciseId, files) => } }); +export const removeAdditionalExerciseFile = (exerciseId, fileId) => + createApiAction({ + type: actionTypes.REMOVE_FILE, + endpoint: `/exercises/${exerciseId}/additional-files/${fileId}`, + method: 'DELETE', + meta: { exerciseId, fileId } + }); + /** * Reducer */ @@ -56,7 +66,11 @@ const reducer = handleActions( createRecord({ data, state: resourceStatus.FULFILLED }) ), state - ) + ), + [actionTypes.REMOVE_FILE_FULFILLED]: ( + state, + { payload, meta: { fileId } } + ) => state.deleteIn(['resources', fileId]) }), initialState ); diff --git a/src/redux/modules/supplementaryFiles.js b/src/redux/modules/supplementaryFiles.js index 3ad0feb22..c6b20f6af 100644 --- a/src/redux/modules/supplementaryFiles.js +++ b/src/redux/modules/supplementaryFiles.js @@ -44,12 +44,12 @@ export const addSupplementaryFiles = (exerciseId, files) => } }); -export const removeSupplementaryFile = fileId => +export const removeSupplementaryFile = (exerciseId, fileId) => createApiAction({ type: actionTypes.REMOVE_FILE, - endpoint: `/uploaded-files/${fileId}`, + endpoint: `/exercises/${exerciseId}/supplementary-files/${fileId}`, method: 'DELETE', - meta: { fileId } + meta: { exerciseId, fileId } }); /**