public/js/cloud_share_modal.js
import React, { createRef } from "react";
import ShareURLComponent from "./share_url";
import _ from "underscore";
/**
* Takes sequence accession as props, fetches the sequence from the server, and
* displays it in a modal.
*/
export default class CloudShareModal extends React.Component {
constructor(props) {
super(props);
this.state = {
formState: 'input', // Possible values: 'input', 'loading', 'results', 'error'
errorMessages: [],
email: '',
agreeToTos: false,
shareableurl: '',
};
this.modalRef = createRef();
}
// Lifecycle methods. //
handleChange = (e) => {
const { name, value, type, checked } = e.target;
const inputValue = type === 'checkbox' ? checked : value;
this.setState({ [name]: inputValue });
}
handleSubmit = (e) => {
e.preventDefault();
const { email } = this.state;
const regex = /\/([^/]+)(?:\/|#|\?|$)/;
const match = window.location.pathname.match(regex);
const jobId = match[1];
this.setState({ formState: 'loading' });
const requestData = {
job_id: jobId,
sender_email: email
};
fetch('/cloud_share', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(requestData)
})
.then(response => response.json())
.then(data => {
if (data.shareable_url) {
// Successful response
this.setState({ formState: 'results', shareableurl: data.shareable_url });
} else if (data.errors) {
// Error response with specific error messages
const errorMessages = data.errors;
this.setState({ formState: 'error', errorMessages });
} else {
// Generic error message
throw new Error('Unknown error submitting form');
}
})
.catch(error => {
this.setState({
formState: 'error',
errorMessages: [error.message]
});
});
}
renderLoading() {
return (
<div className="text-center">
<i className="fa fa-spinner fa-3x fa-spin"></i>
<p>Uploading the job to SequenceServer Cloud, please wait...</p>
</div>
);
}
renderResults() {
const { shareableurl } = this.state;
return <ShareURLComponent url={shareableurl} querydb={this.props.querydb} program={this.props.program} queryLength={this.props.queryLength} />;
}
renderError() {
const { errorMessages } = this.state;
return (
<>
{
_.map(
errorMessages,
_.bind(function (errorMessage) {
return (
<div className="fastan">
<div className="section-content">
<div className="modal-error">{errorMessage}</div>
</div>
</div>
);
}, this)
)
}
{this.renderForm()}
</>
);
}
renderForm() {
const { email, agreeToTos } = this.state;
const isSubmitDisabled = !agreeToTos;
return(
<form onSubmit={this.handleSubmit}>
<div className="form-group">
<label htmlFor="emailInput">Your Email Address</label>
<input
type="email"
id="emailInput"
className="form-control"
placeholder="person@example.com"
name="email"
value={email}
required="required"
onChange={this.handleChange}
/>
</div>
<p>
By submitting this form you agree to upload this SequenceServer result set to <a href="https://sequenceserver.com/cloud/" target="_bank">SenquenceServer Cloud</a>
, where it will become available on the internet to everyone with the link. You also agree that your email address will be stored on SequenceServer databases as proof of authentication for support and similar purposes.
</p>
<div className="form-group form-check">
<input
type="checkbox"
id="tosCheckbox"
className="form-check-input"
name="agreeToTos"
checked={agreeToTos}
onChange={this.handleChange}
/>
<label htmlFor="tosCheckbox" className="form-check-label">
I agree to the <b><a href="https://sequenceserver.com/cloud/terms_and_conditions" target="_blank">Terms and Conditions of Service</a></b>
</label>
</div>
<button type="submit" className="btn btn-primary" disabled={isSubmitDisabled}>
Submit
</button>
</form>
)
}
render() {
const { formState } = this.state;
let content;
switch (formState) {
case 'loading':
content = this.renderLoading();
break;
case 'results':
content = this.renderResults();
break;
case 'error':
content = this.renderError();
break;
case 'input':
default:
content = this.renderForm();
break;
}
return (
<div className="modal cloud-share" ref={this.modalRef} tabIndex="-1">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<h3>Share to SequenceServer Cloud</h3>
</div>
<div className="modal-body">
{content}
</div>
</div>
</div>
</div>
);
}
/*
* Returns jQuery reference to the main modal container.
*/
modal() {
return $(this.modalRef.current);
}
/**
* Shows share dialogue.
*/
show() {
this.setState({ requestCompleted: false }, () => {
this.modal().modal("show");
});
}
/**
* Hide share dialogue.
*/
hide() {
this.modal().modal("hide");
}
}