diff --git a/public/img/fail-kidneys.jpg b/public/img/fail-kidneys.jpg
new file mode 100644
index 0000000..484bb3e
Binary files /dev/null and b/public/img/fail-kidneys.jpg differ
diff --git a/public/img/happy-kidneys.jpg b/public/img/happy-kidneys.jpg
new file mode 100644
index 0000000..674907c
Binary files /dev/null and b/public/img/happy-kidneys.jpg differ
diff --git a/src/actions/Validation/validationActions.js b/src/actions/Validation/validationActions.js
new file mode 100644
index 0000000..9c0baca
--- /dev/null
+++ b/src/actions/Validation/validationActions.js
@@ -0,0 +1,31 @@
+import actionNames from '../actionNames';
+import Api from '../../helpers/Api';
+import { sendMessageToBackend } from '../Error/errorActions';
+
+const api = Api.getInstance();
+
+export const setValidationResult = (result) => {
+ return {
+ type: actionNames.SET_VALIDATION_RESULT,
+ payload: result
+ }
+}
+
+export const validateFilenames = (formData) => {
+ return (dispatch) => {
+ api.post('/api//v1/package/files/validation', formData)
+ .then(res => {
+ dispatch(setValidationResult(res.data));
+ })
+ .catch(error => {
+ console.log(error);
+ dispatch(sendMessageToBackend(error));
+ });
+ }
+}
+
+export const clearValidationResult = () => {
+ return {
+ type: actionNames.CLEAR_VALIDATION_RESULT
+ }
+}
\ No newline at end of file
diff --git a/src/actions/Validation/validationActions.test.js b/src/actions/Validation/validationActions.test.js
new file mode 100644
index 0000000..49d96c6
--- /dev/null
+++ b/src/actions/Validation/validationActions.test.js
@@ -0,0 +1,26 @@
+import actionNames from '../actionNames';
+import { setValidationResult, clearValidationResult } from './validationActions';
+
+describe('setValidationResult', () => {
+ it('should return the result in the correct structure', () => {
+ let expectedResult = {
+ type: actionNames.SET_VALIDATION_RESULT,
+ payload: { 'key': 'value' }
+ };
+
+ let result = setValidationResult({ 'key': 'value' });
+
+ expect(result).toEqual(expectedResult);
+ });
+});
+describe('clearValidationResult', () => {
+ it('should return the result in the correct structure', () => {
+ let expectedResult = {
+ type: actionNames.CLEAR_VALIDATION_RESULT
+ };
+
+ let result = clearValidationResult();
+
+ expect(result).toEqual(expectedResult);
+ });
+});
\ No newline at end of file
diff --git a/src/actions/actionNames.js b/src/actions/actionNames.js
index 819ab34..f00142c 100644
--- a/src/actions/actionNames.js
+++ b/src/actions/actionNames.js
@@ -1,7 +1,9 @@
const actionNames = {
- RESET_STATE: 'RESET_STATE',
- SET_PACKAGES: 'SET_PACKAGES',
- GET_PACKAGES: 'GET_PACKAGES'
+ CLEAR_VALIDATION_RESULT: 'CLEAR_VALIDATION_RESULT',
+ GET_PACKAGES: 'GET_PACKAGES',
+ RESET_STATE: 'RESET_STATE',
+ SET_PACKAGES: 'SET_PACKAGES',
+ SET_VALIDATION_RESULT: 'SET_VALIDATION_RESULT'
};
export default actionNames;
diff --git a/src/components/Validation/FilenameValidationPage.js b/src/components/Validation/FilenameValidationPage.js
index 71b017f..809ad99 100644
--- a/src/components/Validation/FilenameValidationPage.js
+++ b/src/components/Validation/FilenameValidationPage.js
@@ -1,5 +1,7 @@
import React, { Component } from 'react';
import { Container, Row, Col, Button } from 'reactstrap';
+import ValidationSuccess from './ValidationSuccess';
+import ValidationFailure from './ValidationFailure';
class FilenameValidationPage extends Component {
@@ -9,6 +11,7 @@ class FilenameValidationPage extends Component {
packageId: '',
filenames: ''
};
+ this.props.clearValidationResult();
this.handleSubmit = this.handleSubmit.bind(this);
}
@@ -22,41 +25,57 @@ class FilenameValidationPage extends Component {
handleSubmit(e) {
e.preventDefault();
+ this.props.validateFilenames(this.state);
}
render() {
const { packageId, filenames } = this.state;
const isEnabled = packageId.length > 0 && filenames.length > 0;
- return (
-
-
-
- );
+ if (Object.keys(this.props.validationResult).length !== 0 && this.props.validationResult.constructor === Object) {
+ let filesNotInGlobus = this.props.validationResult.metadataFilesNotFoundInGlobus;
+ let filesNotInMetadata = this.props.validationResult.globusFilesNotFoundInMetadata;
+ if (!filesNotInGlobus && !filesNotInMetadata) {
+ return (
+
+ );
+ } else {
+ return (
+
+ );
+ }
+ } else {
+ return (
+
+
+
+ );
+ }
}
}
diff --git a/src/components/Validation/FilenameValidationPageContainer.js b/src/components/Validation/FilenameValidationPageContainer.js
index f8284f3..46992cd 100644
--- a/src/components/Validation/FilenameValidationPageContainer.js
+++ b/src/components/Validation/FilenameValidationPageContainer.js
@@ -1,10 +1,18 @@
import { connect } from 'react-redux';
import FilenameValidationPage from './FilenameValidationPage';
+import { validateFilenames, clearValidationResult } from '../../actions/Validation/validationActions';
const mapStateToProps = (state, props) => ({
+ validationResult: state.filenameValidation
});
const mapDispatchToProps = (dispatch, props) => ({
+ validateFilenames(formData) {
+ dispatch(validateFilenames(formData));
+ },
+ clearValidationResult() {
+ dispatch(clearValidationResult());
+ }
});
export default connect(mapStateToProps, mapDispatchToProps)(FilenameValidationPage);
\ No newline at end of file
diff --git a/src/components/Validation/ValidationFailure.js b/src/components/Validation/ValidationFailure.js
new file mode 100644
index 0000000..43514f6
--- /dev/null
+++ b/src/components/Validation/ValidationFailure.js
@@ -0,0 +1,23 @@
+import React, { Component } from 'react';
+import { Container, Row, Col, Button } from 'reactstrap';
+
+class ValidationFailure extends Component {
+ render() {
+ return(
+
+
+
+
+
+
+
+
+ )
+ }
+}
+
+export default ValidationFailure;
\ No newline at end of file
diff --git a/src/components/Validation/ValidationSuccess.js b/src/components/Validation/ValidationSuccess.js
new file mode 100644
index 0000000..d83e95e
--- /dev/null
+++ b/src/components/Validation/ValidationSuccess.js
@@ -0,0 +1,95 @@
+import React, { Component } from 'react';
+import { Container, Row, Col, Button } from 'reactstrap';
+import { Link } from 'react-router-dom';
+
+class ValidationSuccess extends Component {
+
+ generateTableRows(filesProvided, filesFound) {
+ let rows = [];
+ for (let i=0; i< filesProvided.length; i++) {
+ let fileProvided = filesProvided[i];
+ let fileFound = filesFound[i];
+ rows.push(
+
+
+ {fileProvided}
+
+
+ {fileFound}
+
+
+ );
+ }
+ return rows;
+ }
+
+ render() {
+ let metadataFileName = '';
+ let filesProvided = this.props.result.filesFromMetadata.sort();
+ let filesFound = this.props.result.filesInGlobus.sort();
+ let metadataFileIndex = filesFound.findIndex((file) => file.startsWith('METADATA'));
+ if (metadataFileIndex > -1) {
+ metadataFileName = filesFound[metadataFileIndex];
+ filesFound.splice(metadataFileIndex, 1);
+ }
+ let rows = this.generateTableRows(filesProvided, filesFound);
+
+ return (
+
+
+
+
+
+
+ Validation Success!
+
+
+
+
+ Package Id: {this.props.result.packageId}
+
+
+
+
+
+ Files Provided
+
+
+ Files Found
+
+
+ {rows}
+ {metadataFileName !== '' &&
+
+
+
+
+
+ {metadataFileName}
+
+
+
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+export default ValidationSuccess;
\ No newline at end of file
diff --git a/src/components/Validation/filenameValidationReducer.js b/src/components/Validation/filenameValidationReducer.js
new file mode 100644
index 0000000..40b0231
--- /dev/null
+++ b/src/components/Validation/filenameValidationReducer.js
@@ -0,0 +1,15 @@
+import actionNames from '../../actions/actionNames';
+
+export const filenameValidation = (state = {}, action) => {
+ let newState = {};
+
+ switch (action.type) {
+ case actionNames.SET_VALIDATION_RESULT:
+ newState = action.payload;
+ return newState;
+ case actionNames.CLEAR_VALIDATION_RESULT:
+ return newState;
+ default:
+ return state;
+ }
+}
diff --git a/src/components/Validation/filenameValidationReducer.test.js b/src/components/Validation/filenameValidationReducer.test.js
new file mode 100644
index 0000000..7c566da
--- /dev/null
+++ b/src/components/Validation/filenameValidationReducer.test.js
@@ -0,0 +1,25 @@
+import { filenameValidation } from './filenameValidationReducer';
+import actionNames from '../../actions/actionNames';
+
+describe('filenameValidation', () => {
+ it('should return the given state if not known action', () => {
+ let action = {
+ type: 'UNKNOWN'
+ };
+ expect(filenameValidation({}, action)).toEqual({});
+ });
+
+ it('should return the new state if SET_VALIDATION_RESULT', () => {
+ let action = {
+ type: actionNames.SET_VALIDATION_RESULT,
+ payload: 'new stuff'
+ };
+ expect(filenameValidation({}, action)).toEqual('new stuff');
+ });
+ it('should clear the state if CLEAR_VALIDATION_RESULT', () => {
+ let action = {
+ type: actionNames.CLEAR_VALIDATION_RESULT
+ };
+ expect(filenameValidation({'key': 'value'}, action)).toEqual({});
+ });
+});
\ No newline at end of file
diff --git a/src/index.css b/src/index.css
index 920cf00..c4d3ab4 100644
--- a/src/index.css
+++ b/src/index.css
@@ -52,3 +52,18 @@ body {
@media only screen and (max-width: 767px) {
#title-text {
display: none; } }
+
+.validationImage {
+ height: 150px; }
+
+.validationMessage {
+ vertical-align: bottom;
+ height: 150px;
+ display: table-cell; }
+
+.resultHeader {
+ background-color: lightgray;
+ font-weight: 700; }
+
+.heavierText {
+ font-weight: 700; }
diff --git a/src/index.scss b/src/index.scss
index 095a4e5..6582047 100644
--- a/src/index.scss
+++ b/src/index.scss
@@ -1 +1,20 @@
-@import "kpmp-base.scss";
\ No newline at end of file
+@import "kpmp-base.scss";
+
+.validationImage {
+ height: 150px;
+}
+
+.validationMessage {
+ vertical-align: bottom;
+ height: 150px;
+ display: table-cell;
+}
+
+.resultHeader {
+ background-color: lightgray;
+ font-weight: 700;
+}
+
+.heavierText {
+ font-weight: 700;
+}
\ No newline at end of file
diff --git a/src/reducers.js b/src/reducers.js
index a9d7617..bb5359a 100644
--- a/src/reducers.js
+++ b/src/reducers.js
@@ -1,12 +1,14 @@
import { combineReducers } from 'redux';
import { resetStateReducer } from './resetStateReducer';
import { packages } from './components/PackageDashboard/packageReducer';
+import { filenameValidation } from './components/Validation/filenameValidationReducer';
import actionNames from './actions/actionNames';
import loadedState from './initialState';
const appReducer = combineReducers({
- resetStateReducer,
- packages
+ filenameValidation,
+ resetStateReducer,
+ packages
});
const rootReducer = (state, action) => {