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/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/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
);