Skip to content
Snippets Groups Projects
Unverified Commit 2d2015f4 authored by Awais Jibran's avatar Awais Jibran Committed by GitHub
Browse files

Merge pull request #23981 from edx/aj/details/code-refactor

Code Refactor
parents c7f4e164 6b8ebd5a
Branches
Tags
No related merge requests found
......@@ -6,25 +6,23 @@ import PropTypes from 'prop-types';
class ShowErrors extends React.Component {
render() {
if (this.props.errorList.length > 0) {
window.scrollTo(0, 0);
}
return this.props.errorList.length > 0 &&
<div className="col-sm-12">
return (
this.props.hasErrors && <div className="col-sm-12">
<div className="alert alert-danger" role="alert">
<strong>{gettext('Please fix the following errors:')}</strong>
<ul>
{this.props.errorList.map((error, i) =>
<li key={i}>{error}</li>,
{ Object.keys(this.props.errorList).map(key =>
this.props.errorList[key] && <li key={key}>{this.props.errorList[key]}</li>,
)}
</ul>
</div>
</div>;
</div>);
}
}
ShowErrors.propTypes = {
errorList: PropTypes.arrayOf(PropTypes.object).isRequired,
errorList: PropTypes.objectOf(PropTypes.string).isRequired,
hasErrors: PropTypes.bool.isRequired,
};
export default ShowErrors;
......@@ -5,8 +5,7 @@ import PropTypes from 'prop-types';
import { Button, StatusAlert } from '@edx/paragon';
import StringUtils from 'edx-ui-toolkit/js/utils/string-utils';
function LoggedInUser({ userInformation, onChangeCallback, submitForm, showWarning, showDiscussionButton, reDirectUser }) {
function LoggedInUser({ userInformation, onChangeCallback, submitForm, showWarning, showDiscussionButton, reDirectUser, errorList }) {
let courseElement;
let detailElement;
let discussionElement = '';
......@@ -97,7 +96,7 @@ function LoggedInUser({ userInformation, onChangeCallback, submitForm, showWarni
<div>
<div className="row">
<div className="col-sm-12">
<div className="form-group">
<div className={`form-group ${errorList.message ? 'has-error' : ''}`}>
<label htmlFor="message">{gettext('Details')}</label>
<p className="message-desc">{gettext('the more quickly and helpfully we can respond!')}</p>
<textarea aria-describedby="message" className="form-control" rows="7" id="message" />
......@@ -138,7 +137,7 @@ function LoggedInUser({ userInformation, onChangeCallback, submitForm, showWarni
<div className="row">
<div className="col-sm-12">
<div className="form-group">
<div className={`form-group ${errorList.subject ? 'has-error' : ''}`}>
{subjectElement}
</div>
</div>
......@@ -146,7 +145,7 @@ function LoggedInUser({ userInformation, onChangeCallback, submitForm, showWarni
<div className="row">
<div className="col-sm-12">
<div className="form-group">
<div className={`form-group ${errorList.course ? 'has-error' : ''}`}>
{courseElement}
</div>
</div>
......@@ -174,6 +173,7 @@ LoggedInUser.propTypes = {
}).isRequired,
showWarning: PropTypes.bool.isRequired,
showDiscussionButton: PropTypes.bool.isRequired,
errorList: PropTypes.objectOf(PropTypes.string).isRequired,
};
export default LoggedInUser;
......@@ -14,140 +14,158 @@ import LoggedInUser from './logged_in_user';
import LoggedOutUser from './logged_out_user';
import Success from './success';
const initialFormErrors = {
course: undefined,
subject: undefined,
message: undefined,
request: undefined,
};
class RenderForm extends React.Component {
constructor(props) {
super(props);
this.submitFormUrl = this.props.context.submitFormUrl;
this.userInformation = this.props.context.user;
const course = this.userInformation ? this.userInformation.course_id : '';
this.courseDiscussionURL = '/courses/{course_id}/discussion/forum';
this.state = {
currentRequest: null,
errorList: [],
errorList: initialFormErrors,
success: false,
formData: {
course,
subject: '',
message: '',
course,
},
};
this.formValidationErrors = {
course: gettext('Select a course or select "Not specific to a course" for your support request.'),
subject: gettext('Select a subject for your support request.'),
message: gettext('Enter some details for your support request.'),
request: gettext('Something went wrong. Please try again later.'),
};
this.submitForm = this.submitForm.bind(this);
this.reDirectUser = this.reDirectUser.bind(this);
this.setErrorState = this.setErrorState.bind(this);
this.formOnChangeCallback = this.formOnChangeCallback.bind(this);
this.showWarningMessage = this.showWarningMessage.bind(this);
this.showDiscussionButton = this.showDiscussionButton.bind(this);
}
setErrorState(errors) {
getFormDataFromState() {
return this.state.formData;
}
getFormErrorsFromState() {
return this.state.errorList;
}
clearErrorState() {
const formErrorsInState = this.getFormErrorsFromState();
Object.keys(formErrorsInState).map((index) => {
formErrorsInState[index] = undefined;
return formErrorsInState;
});
}
// eslint-disable-next-line class-methods-use-this
scrollToTop() {
return window.scrollTo(0, 0);
}
formHasErrors() {
const errorsList = this.getFormErrorsFromState();
return Object.keys(errorsList).filter(err => errorsList[err] !== undefined).length > 0;
}
updateErrorInState(key, error) {
const errorList = this.getFormErrorsFromState();
errorList[key] = error;
this.setState({
errorList: errors,
errorList,
});
}
formOnChangeCallback(event) {
const eventTarget = event.target;
let formData = this.state.formData;
formData[eventTarget.id] = eventTarget.value;
const formData = this.getFormDataFromState();
formData[event.target.id] = event.target.value;
this.setState({ formData });
}
showWarningMessage() {
return this.state.formData && this.state.formData.subject === 'Course Content';
const formData = this.getFormDataFromState(),
selectedSubject = formData.subject;
return formData && selectedSubject === 'Course Content';
}
showDiscussionButton() {
const selectCourse = this.state.formData.course;
return this.state.formData && (selectCourse !== '' && selectCourse !== 'Not specific to a course');
const formData = this.getFormDataFromState(),
selectedCourse = formData.course;
return formData && (selectedCourse !== '' && selectedCourse !== 'Not specific to a course');
}
reDirectUser(event) {
event.preventDefault();
window.location.href = `/courses/${this.state.formData.course}/discussion/forum`;
const formData = this.getFormDataFromState();
window.location.href = this.courseDiscussionURL.replace('{course_id}', formData.course);
}
submitForm(event) {
event.preventDefault();
let subject,
course;
const url = this.props.context.submitFormUrl,
const formData = this.getFormDataFromState();
this.clearErrorState();
this.validateFormData(formData);
if (this.formHasErrors()) {
return this.scrollToTop();
}
this.createZendeskTicket(formData);
}
createZendeskTicket(formData) {
const url = this.submitFormUrl,
request = new XMLHttpRequest(),
$course = $('#course'),
$subject = $('#subject'),
data = {
comment: {
body: this.state.formData.message,
body: formData.message,
},
subject: formData.subject, // Zendesk API requires 'subject'
custom_fields: [{
id: this.props.context.customFields.course_id,
value: formData.course,
}],
tags: this.props.context.tags,
},
errors = [];
this.clearErrors();
data.requester = {
email: this.userInformation.email,
name: this.userInformation.username,
};
course = $course.find(':selected').val();
if (!course) {
course = $course.val();
}
if (!course) {
$('#course').closest('.form-group').addClass('has-error');
errors.push(gettext('Select a course or select "Not specific to a course" for your support request.'));
}
data.custom_fields = [{
id: this.props.context.customFields.course_id,
value: course,
}];
subject = $subject.find(':selected').val();
if (!subject) {
subject = $subject.val();
}
if (!subject) {
$subject.closest('.form-group').addClass('has-error');
errors.push(gettext('Select a subject for your support request.'));
}
data.subject = subject; // Zendesk API requires 'subject'
if (this.validateData(data, errors)) {
request.open('POST', url, true);
request.setRequestHeader('Content-type', 'application/json;charset=UTF-8');
request.setRequestHeader('X-CSRFToken', $.cookie('csrftoken'));
request.send(JSON.stringify(data));
request.onreadystatechange = function success() {
if (request.readyState === 4 && request.status === 201) {
this.setState({
success: true,
});
}
}.bind(this);
request.onerror = function error() {
this.setErrorState([gettext('Something went wrong. Please try again later.')]);
}.bind(this);
}
}
clearErrors() {
this.setErrorState([]);
$('.form-group').removeClass('has-error');
requester: {
email: this.userInformation.email,
name: this.userInformation.username,
},
};
request.open('POST', url, true);
request.setRequestHeader('Content-type', 'application/json;charset=UTF-8');
request.setRequestHeader('X-CSRFToken', $.cookie('csrftoken'));
request.send(JSON.stringify(data));
request.onreadystatechange = function success() {
if (request.readyState === 4 && request.status === 201) {
this.setState({
success: true,
});
}
}.bind(this);
request.onerror = function error() {
this.updateErrorInState('request', this.formValidationErrors.request);
this.scrollToTop();
}.bind(this);
}
validateData(data, errors) {
if (!data.comment.body) {
errors.push(gettext('Enter some details for your support request.'));
$('#message').closest('.form-group').addClass('has-error');
}
if (!errors.length) {
return true;
}
this.setErrorState(errors);
return false;
validateFormData(formData) {
const { course, subject, message } = formData;
let courseError,
subjectError,
messageError;
courseError = (course === '') ? this.formValidationErrors.course : undefined;
this.updateErrorInState('course', courseError);
subjectError = (subject === '') ? this.formValidationErrors.subject : undefined;
this.updateErrorInState('subject', subjectError);
messageError = (message === '') ? this.formValidationErrors.message : undefined;
this.updateErrorInState('message', messageError);
}
renderSuccess() {
......@@ -171,6 +189,7 @@ class RenderForm extends React.Component {
showWarning={this.showWarningMessage()}
showDiscussionButton={this.showDiscussionButton()}
reDirectUser={this.reDirectUser}
errorList={this.getFormErrorsFromState()}
/>);
} else {
userElement = (<LoggedOutUser
......@@ -194,9 +213,8 @@ class RenderForm extends React.Component {
<h2>{gettext('Contact Us')}</h2>
</div>
</div>
<div className="row form-errors">
<ShowErrors errorList={this.state.errorList} />
<ShowErrors errorList={this.getFormErrorsFromState()} hasErrors={this.formHasErrors()} />
</div>
<div className="row">
......@@ -228,7 +246,6 @@ class RenderForm extends React.Component {
if (this.state.success) {
return this.renderSuccess();
}
return this.renderSupportForm();
}
}
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment