diff --git a/src/components/SubmissionFailures/FailuresList/FailuresList.js b/src/components/SubmissionFailures/FailuresList/FailuresList.js
new file mode 100644
index 000000000..a285873d4
--- /dev/null
+++ b/src/components/SubmissionFailures/FailuresList/FailuresList.js
@@ -0,0 +1,72 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { Table } from 'react-bootstrap';
+import { FormattedMessage } from 'react-intl';
+import FailuresListItem from '../FailuresListItem';
+
+const FailuresList = ({ failures, createActions }) =>
+
+
+
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+ |
+ |
+
+
+
+ {failures.map((failure, i) =>
+
+ )}
+
+ {failures.length === 0 &&
+
+
+
+ |
+
}
+
+
;
+
+FailuresList.propTypes = {
+ failures: PropTypes.array,
+ createActions: PropTypes.func,
+ failure: PropTypes.object
+};
+
+export default FailuresList;
diff --git a/src/components/SubmissionFailures/FailuresList/index.js b/src/components/SubmissionFailures/FailuresList/index.js
new file mode 100644
index 000000000..5290225a3
--- /dev/null
+++ b/src/components/SubmissionFailures/FailuresList/index.js
@@ -0,0 +1 @@
+export default from './FailuresList';
diff --git a/src/components/SubmissionFailures/FailuresListItem/FailuresListItem.js b/src/components/SubmissionFailures/FailuresListItem/FailuresListItem.js
new file mode 100644
index 000000000..bd36c1553
--- /dev/null
+++ b/src/components/SubmissionFailures/FailuresListItem/FailuresListItem.js
@@ -0,0 +1,60 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { FormattedDate, FormattedTime } from 'react-intl';
+import Icon from 'react-fontawesome';
+import { OverlayTrigger, Tooltip } from 'react-bootstrap';
+
+const FailuresListItem = ({ id, createActions, failure }) =>
+
+
+
+ {failure.type}
+
+ }
+ >
+
+ {failure.type === 'broker_reject' && }
+ {failure.type === 'evaluation_failure' && }
+ {failure.type === 'loading_failure' && }
+
+
+ |
+
+ {failure.description}
+ |
+
+
+ {', '}
+
+ |
+
+ {failure.resolvedAt
+ ?
+
+ {', '}
+
+
+ : —}
+ |
+
+ {failure.resolutionNote
+ ?
+ {failure.resolutionNote}
+
+ : —}
+ |
+
+ {createActions && createActions(id)}
+ |
+
;
+
+FailuresListItem.propTypes = {
+ id: PropTypes.string.isRequired,
+ failure: PropTypes.object.isRequired,
+ createActions: PropTypes.func
+};
+
+export default FailuresListItem;
diff --git a/src/components/SubmissionFailures/FailuresListItem/index.js b/src/components/SubmissionFailures/FailuresListItem/index.js
new file mode 100644
index 000000000..87ad69694
--- /dev/null
+++ b/src/components/SubmissionFailures/FailuresListItem/index.js
@@ -0,0 +1 @@
+export default from './FailuresListItem';
diff --git a/src/pages/SubmissionFailures/SubmissionFailures.js b/src/pages/SubmissionFailures/SubmissionFailures.js
index 19cb0f1a1..9406c1be8 100644
--- a/src/pages/SubmissionFailures/SubmissionFailures.js
+++ b/src/pages/SubmissionFailures/SubmissionFailures.js
@@ -3,12 +3,18 @@ import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { FormattedMessage } from 'react-intl';
-import Page from '../../components/layout/Page';
-import ResourceRenderer from '../../components/helpers/ResourceRenderer';
+import PageContent from '../../components/layout/PageContent';
+import FetchManyResourceRenderer from '../../components/helpers/FetchManyResourceRenderer';
import { fetchAllFailures } from '../../redux/modules/submissionFailures';
+import {
+ fetchManyStatus,
+ readySubmissionFailuresSelector
+} from '../../redux/selectors/submissionFailures';
+import FailuresList from '../../components/SubmissionFailures/FailuresList/FailuresList';
+import Box from '../../components/widgets/Box/Box';
class SubmissionFailures extends Component {
- static loadAsync = ({}, dispatch) =>
+ static loadAsync = (params, dispatch) =>
Promise.all([dispatch(fetchAllFailures)]);
componentWillMount() {
@@ -16,48 +22,100 @@ class SubmissionFailures extends Component {
}
render() {
- const { submissionFailures = [] } = this.props;
+ const { submissionFailures, fetchStatus } = this.props;
return (
-
+ }
+ description={
+
+ }
/>
}
- description={
-
+ }
+ description={
+
+ }
/>
}
- breadcrumbs={[
- {
- text: (
+ >
+ {() =>
+
- ),
- iconName: 'fort-awesome'
- }
- ]}
- >
-
-
+ }
+ description={
+
+ }
+ breadcrumbs={[
+ {
+ text: (
+
+ ),
+ iconName: 'fort-awesome'
+ }
+ ]}
+ >
+
+ }
+ unlimitedHeight
+ noPadding
+ >
+
+
+ }
+
);
}
}
SubmissionFailures.propTypes = {
- loadAsync: PropTypes.func.isRequired
+ loadAsync: PropTypes.func.isRequired,
+ fetchStatus: PropTypes.string,
+ submissionFailures: PropTypes.array
};
export default connect(
- (state, { params: {} }) => ({}),
- (dispatch, { params }) => ({
- loadAsync: () => SubmissionFailures.loadAsync(params, dispatch)
+ state => ({
+ fetchStatus: fetchManyStatus(state),
+ submissionFailures: readySubmissionFailuresSelector(state)
+ }),
+ dispatch => ({
+ loadAsync: () => SubmissionFailures.loadAsync({}, dispatch)
})
)(SubmissionFailures);
diff --git a/src/redux/modules/submissionFailures.js b/src/redux/modules/submissionFailures.js
index 0deb02561..90ce9e28c 100644
--- a/src/redux/modules/submissionFailures.js
+++ b/src/redux/modules/submissionFailures.js
@@ -1,14 +1,13 @@
-import { handleActions, createAction } from 'redux-actions';
-import factory, {
- initialState,
- resourceStatus
-} from '../helpers/resourceManager';
+import { handleActions } from 'redux-actions';
+import factory, { initialState } from '../helpers/resourceManager';
import { createApiAction } from '../middleware/apiMiddleware';
const resourceName = 'submissionFailures';
-var { actions, actionTypes, reduceActions } = factory({ resourceName });
+var { actions, reduceActions } = factory({ resourceName });
-export const additionalActionTypes = {};
+export const additionalActionTypes = {
+ RESOLVE: 'recodex/submissionFailures/RESOLVE'
+};
/**
* Actions
@@ -19,6 +18,15 @@ export const fetchAllFailures = actions.fetchMany({
endpoint: fetchManyEndpoint
});
+export const resolveFailure = (id, note) =>
+ createApiAction({
+ type: additionalActionTypes.RESOLVE,
+ method: 'POST',
+ endpoint: `/submission-failures/${id}/resolve`,
+ body: { note },
+ meta: { id }
+ });
+
/**
* Reducer takes mainly care about all the state of individual attachments
*/
diff --git a/src/redux/selectors/submissionFailures.js b/src/redux/selectors/submissionFailures.js
new file mode 100644
index 000000000..f8b9ab099
--- /dev/null
+++ b/src/redux/selectors/submissionFailures.js
@@ -0,0 +1,31 @@
+import { createSelector } from 'reselect';
+import { fetchManyEndpoint } from '../modules/submissionFailures';
+import { isReady, getJsData } from '../helpers/resourceManager';
+
+const getSubmissionFailures = state => state.submissionFailures;
+const getResources = failures => failures.get('resources');
+
+export const submissionFailuresSelector = createSelector(
+ getSubmissionFailures,
+ getResources
+);
+
+export const fetchManyStatus = createSelector(getSubmissionFailures, state =>
+ state.getIn(['fetchManyStatus', fetchManyEndpoint])
+);
+
+export const getSubmissionFailure = failureId =>
+ createSelector(submissionFailuresSelector, failures =>
+ failures.get(failureId)
+ );
+
+export const readySubmissionFailuresSelector = createSelector(
+ submissionFailuresSelector,
+ failures =>
+ failures
+ .toList()
+ .filter(isReady)
+ .map(getJsData)
+ .sort((a, b) => a.createdAt - b.createdAt)
+ .toArray()
+);