Course Content boilerplate blurb (and link to discussions)

PROD-1475
This commit is contained in:
jinder1s
2020-04-16 15:09:51 -04:00
committed by Awais Jibran
parent 0d8c99aa2f
commit ae2c2c4765
3 changed files with 175 additions and 86 deletions

View File

@@ -14,8 +14,8 @@ class ShowErrors extends React.Component {
<div className="alert alert-danger" role="alert">
<strong>{gettext('Please fix the following errors:')}</strong>
<ul>
{this.props.errorList.map(error =>
<li>{error}</li>,
{this.props.errorList.map((error, i) =>
<li key={i}>{error}</li>,
)}
</ul>
</div>

View File

@@ -2,29 +2,34 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Button, StatusAlert } from '@edx/paragon';
import StringUtils from 'edx-ui-toolkit/js/utils/string-utils';
import FileUpload from './file_upload';
function LoggedInUser({ userInformation, setErrorState, zendeskApiHost, submitForm }) {
function LoggedInUser({ userInformation, onChangeCallback, submitForm, showWarning, showDiscussionButton, reDirectUser }) {
let courseElement;
let detailElement;
let discussionElement = '';
if (userInformation.enrollments) {
courseElement = (<div>
<label className="label-course" htmlFor="course">{gettext('Course Name')}</label>
<p className="message-desc"><i>
{gettext('For inquiries regarding assignments, grades, or structure of a specific course, please post in the discussion forums for that course directly.')}
{gettext('For inquiries regarding assignments, grades, or structure of a specific course, please post in the discussion forums for that course directly.')}
</i></p>
<select className="form-control select-course" id="course" defaultValue={userInformation.course_id}>
<select
className="form-control select-course"
id="course"
defaultValue={userInformation.course_id}
>
<option key="select-course" value="">--------</option>
<option key="not-course-specific" value="Not specific to a course">
{gettext('Not specific to a course')}
</option>
{userInformation.enrollments.map(enrollment =>
(<option key={enrollment.course_id} value={enrollment.course_id}>
{enrollment.course_name}
</option>),
)}
(<option key={enrollment.course_id} value={enrollment.course_id}>
{enrollment.course_name}
</option>),
)}
</select>
</div>);
} else {
@@ -33,11 +38,9 @@ function LoggedInUser({ userInformation, setErrorState, zendeskApiHost, submitFo
<input type="text" className="form-control" id="course" />
</div>);
}
let topicElement;
topicElement = (<div>
<label htmlFor="topic">{gettext('Topic')}</label>
<select className="form-control select-subject" id="topic">
const subjectElement = (<div>
<label htmlFor="subject">{gettext('Subject')}</label>
<select className="form-control select-subject" id="subject">
<option value="">--------</option>
<option value="Account Settings">{gettext('Account Settings')}</option>
<option value="Billing/Payment Options">{gettext('Billing/Payment Options')}</option>
@@ -55,10 +58,68 @@ function LoggedInUser({ userInformation, setErrorState, zendeskApiHost, submitFo
<option value="Other">{gettext('Other')}</option>
</select>
</div>);
if (showDiscussionButton) {
discussionElement = (
<div className="row">
<div className="col-sm-12">
<Button
className={['btn', 'btn-primary', 'btn-submit']}
onClick={reDirectUser}
label={gettext('Course Discussion Forum')}
/>
</div>
</div>
);
}
if (showWarning) {
detailElement = (
<div id="warning-msg">
<div className="row">
<div className="col-sm-12">
<div className="form-group">
<StatusAlert
alertType="info"
className={['in', 'pattern-library-shim']}
dismissible={false}
dialog={
gettext('While our support team is happy to assist with the edX platform, the course staff has the expertise for specific assignment questions, grading or the proper procedures in each course. Please post all course related questions within the Discussion Forum where the Course Staff can directly respond.')
}
open
/>
</div>
</div>
</div>
{ discussionElement }
</div>
);
} else {
detailElement = (
<div>
<div className="row">
<div className="col-sm-12">
<div className="form-group">
<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" />
</div>
</div>
</div>
<div className="row">
<div className="col-sm-12">
<Button
className={['btn', 'btn-primary', 'btn-submit']}
type="submit"
label={gettext('Create Support Ticket')}
/>
</div>
</div>
</div>
);
}
return (<div>
return (<form id="contact-us-form" onSubmit={submitForm} onChange={onChangeCallback}>
<div className="row">
<hr className="col-sm-12"></hr>
<hr className="col-sm-12" />
</div>
<div className="row">
<div
@@ -75,6 +136,14 @@ function LoggedInUser({ userInformation, setErrorState, zendeskApiHost, submitFo
</div>
</div>
<div className="row">
<div className="col-sm-12">
<div className="form-group">
{subjectElement}
</div>
</div>
</div>
<div className="row">
<div className="col-sm-12">
<div className="form-group">
@@ -82,55 +151,29 @@ function LoggedInUser({ userInformation, setErrorState, zendeskApiHost, submitFo
</div>
</div>
</div>
<div className="row">
<div className="col-sm-12">
<div className="form-group">
{topicElement}
</div>
</div>
</div>
<div className="row">
<div className="col-sm-12">
<div className="form-group">
<label htmlFor="message">{gettext('Details')}</label>
<p
className="message-desc"
>{gettext('The more you tell us, the more quickly and helpfully we can respond!')}</p>
<textarea
aria-describedby="message"
className="form-control"
rows="7"
id="message"
/>
</div>
</div>
</div>
{/* TODO file uploading will be done after initial release */}
{/* <FileUpload */}
{/* setErrorState={setErrorState} */}
{/* zendeskApiHost={zendeskApiHost} */}
{/* accessToken={accessToken} */}
{/* /> */}
<div className="row">
<div className="col-sm-12">
<button
className="btn btn-primary btn-submit"
onClick={submitForm}
>{gettext('Create Support Ticket')}</button>
</div>
</div>
</div>);
{detailElement}
</form>);
}
/* TODO file uploading will be done after initial release */
/* <FileUpload */
/* setErrorState={setErrorState} */
/* zendeskApiHost={zendeskApiHost} */
/* accessToken={accessToken} */
/* /> */
LoggedInUser.propTypes = {
setErrorState: PropTypes.func.isRequired,
submitForm: PropTypes.func.isRequired,
userInformation: PropTypes.arrayOf(PropTypes.object).isRequired,
submitFormUrl: PropTypes.string.isRequired,
onChangeCallback: PropTypes.func.isRequired,
reDirectUser: PropTypes.func.isRequired,
userInformation: PropTypes.shape({
course_id: PropTypes.string,
username: PropTypes.string,
email: PropTypes.string,
enrollments: PropTypes.arrayOf(PropTypes.object),
}).isRequired,
showWarning: PropTypes.bool.isRequired,
showDiscussionButton: PropTypes.bool.isRequired,
};
export default LoggedInUser;

View File

@@ -5,6 +5,7 @@
import PropTypes from 'prop-types';
import React from 'react';
import ReactDOM from 'react-dom';
import { StatusAlert } from '@edx/paragon';
import StringUtils from 'edx-ui-toolkit/js/utils/string-utils';
@@ -17,13 +18,24 @@ import Success from './success';
class RenderForm extends React.Component {
constructor(props) {
super(props);
this.userInformation = this.props.context.user;
const course = this.userInformation ? this.userInformation.course_id : '';
this.state = {
currentRequest: null,
errorList: [],
success: false,
formData: {
subject: '',
message: '',
course,
},
};
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) {
@@ -32,26 +44,48 @@ class RenderForm extends React.Component {
});
}
submitForm() {
formOnChangeCallback(event) {
const eventTarget = event.target;
let formData = this.state.formData;
formData[eventTarget.id] = eventTarget.value;
this.setState({ formData });
}
showWarningMessage() {
return this.state.formData && this.state.formData.subject === 'Course Content';
}
showDiscussionButton() {
const selectCourse = this.state.formData.course;
return this.state.formData && (selectCourse !== '' && selectCourse !== 'Not specific to a course');
}
reDirectUser(event) {
event.preventDefault();
window.location.href = `/courses/${this.state.formData.course}/discussion/forum`;
}
submitForm(event) {
event.preventDefault();
let subject,
course;
const url = this.props.context.submitFormUrl,
$userInfo = $('.user-info'),
request = new XMLHttpRequest(),
$course = $('#course'),
$topic = $('#topic'),
$subject = $('#subject'),
data = {
comment: {
body: $('#message').val(),
body: this.state.formData.message,
},
tags: this.props.context.tags,
},
errors = [];
let course;
this.clearErrors();
data.requester = {
email: $userInfo.data('email'),
name: $userInfo.data('username'),
email: this.userInformation.email,
name: this.userInformation.username,
};
course = $course.find(':selected').val();
@@ -66,17 +100,15 @@ class RenderForm extends React.Component {
id: this.props.context.customFields.course_id,
value: course,
}];
let topic;
topic = $topic.find(':selected').val();
if (!topic) {
topic = $topic.val();
subject = $subject.find(':selected').val();
if (!subject) {
subject = $subject.val();
}
if (!topic) {
$('#topic').closest('.form-group').addClass('has-error');
errors.push(gettext('Select a topic for your support request.'));
if (!subject) {
$subject.closest('.form-group').addClass('has-error');
errors.push(gettext('Select a subject for your support request.'));
}
data.subject = topic; // Zendesk API requires 'subject'
data.subject = subject; // Zendesk API requires 'subject'
if (this.validateData(data, errors)) {
request.open('POST', url, true);
@@ -124,19 +156,21 @@ class RenderForm extends React.Component {
platformName={this.props.context.platformName}
homepageUrl={this.props.context.homepageUrl}
dashboardUrl={this.props.context.dashboardUrl}
isLoggedIn={this.props.context.user !== undefined}
isLoggedIn={this.userInformation !== undefined}
/>
);
}
renderSupportForm() {
let userElement;
if (this.props.context.user) {
if (this.userInformation) {
userElement = (<LoggedInUser
userInformation={this.props.context.user}
submitFormUrl={this.props.context.submitFormUrl}
setErrorState={this.setErrorState}
userInformation={this.userInformation}
onChangeCallback={this.formOnChangeCallback}
submitForm={this.submitForm}
showWarning={this.showWarningMessage()}
showDiscussionButton={this.showDiscussionButton()}
reDirectUser={this.reDirectUser}
/>);
} else {
userElement = (<LoggedOutUser
@@ -149,7 +183,8 @@ class RenderForm extends React.Component {
return (
<div className="contact-us-wrapper">
{/* Note: not using Paragon bc component shows in the DOM but not rendered, even when using version 2.6.4. */}
{/* Note: not using Paragon bc component shows in the DOM but not rendered, even when using
version 2.6.4. */}
<div className="alert alert-warning" role="alert" style={{ marginBottom: '1rem', padding: '1.5rem', left: '0px', fontSize: '16px', backgroundColor: '#fffaed', color: '#171C29', border: '1px solid #FFD875', borderRadius: '0.3rem' }}>
<div>{gettext('Due to the recent increase in interest in online education and edX, we are currently experiencing an unusually high volume of support requests. We appreciate your patience as we work to review each request. Please check the ')}<a href="https://support.edx.org/hc/en-us" className="alert-link">Help Center</a>{gettext(' as many questions may have already been answered.')}</div>
</div>
@@ -199,7 +234,18 @@ class RenderForm extends React.Component {
}
RenderForm.propTypes = {
context: PropTypes.arrayOf(PropTypes.object).isRequired,
context: PropTypes.shape({
customFields: PropTypes.object,
dashboardUrl: PropTypes.string,
homepageUrl: PropTypes.string,
marketingUrl: PropTypes.string,
loginQuery: PropTypes.string,
platformName: PropTypes.string,
submitFormUrl: PropTypes.string,
supportEmail: PropTypes.string,
tags: PropTypes.arrayOf(PropTypes.string),
user: PropTypes.object,
}).isRequired,
};
export class SingleSupportForm {