trc-client-core
Version:
The core of the TRC Client
347 lines (311 loc) • 13.5 kB
JSX
/*global window, document*/
import React from 'react';
import ReactDOM from 'react-dom'
import PureRenderMixin from 'react-addons-pure-render-mixin';
import _ from 'lodash';
import Reflux from 'reflux';
import StoreMixin from 'reflux-immutable/StoreMixin';
import Button from 'bd-stampy/components/Button';
import CourseActions from 'trc-client-core/src/course/CourseActions';
import CourseActivityHistory from 'trc-client-core/src/course/CourseActivityHistory';
import CourseStore from 'trc-client-core/src/course/CourseStore';
import Icon from 'trc-client-core/src/components/Icon';
import Loader from 'trc-client-core/src/components/Loader';
import ManagerSelectForm from 'trc-client-core/src/course/ManagerSelectForm';
import ModalView from 'trc-client-core/src/components/ModalView';
import PathwayStore from 'trc-client-core/src/course/PathwayStore';
import RegistrationActions from 'trc-client-core/src/course/RegistrationActions';
import RegistrationSingle from 'trc-client-core/src/course/RegistrationSingle';
import RegistrationStore from 'trc-client-core/src/course/RegistrationStore';
import SodataStore from 'trc-client-core/src/sodata/SodataStore';
import UserStore from 'trc-client-core/src/user/UserStore';
import Video from 'trc-client-core/src/components/Video';
var CourseActivityModal = React.createClass({
displayName: 'CourseActivityModal',
mixins: [
Reflux.listenTo(SodataStore, 'onStoreChange'),
Reflux.listenTo(CourseStore, 'onStoreChange'),
Reflux.listenTo(RegistrationStore, 'onStoreChange'),
PureRenderMixin,
StoreMixin
],
propTypes: {
courseCode: React.PropTypes.string.isRequired,
participantId: React.PropTypes.string.isRequired,
actionable: React.PropTypes.bool
},
getDefaultProps() {
return {
actionable: true
};
},
getStoreState() {
return {
course: CourseStore.get('course'),
soData: SodataStore.get('soData'),
fetchingParticipation: CourseStore.get('fetchingParticipation'),
fetchingCourse: CourseStore.get('fetchingCourse'),
participation: CourseStore.get('participation')
};
},
getInitialState () {
return {
selectSoItem: null,
soId: null,
managers: null,
videoButtonDisabled: true
};
},
componentDidMount() {
var query = {
courseCode: this.props.courseCode,
participantId: this.props.participantId
};
CourseActions.fetchCourse(query.courseCode);
CourseActions.fetchParticipation(query);
},
onRequestChange(e, details) {
this.setState(details);
},
onRequestEvaluation() {
ReactDOM.findDOMNode(this.refs.form).submit();
},
onRequestSubmit() {
if(UserStore.is('ROLE_MANAGER')) {
RegistrationActions.sendRegistrationData([{
participantId: this.props.participantId,
soId: this.state.soId,
courseCode: this.props.courseCode,
operation: 'ENROLL',
regId: null,
operator: UserStore.get('username'),
message: null
}]);
} else {
RegistrationActions.requestTraining(this.state.manager, this.state.soId);
}
this.onClose();
},
//
// Product Pathway modal specifics
// TODO: remove to a more generic completion endpoint
//
startThenCompleteCourse() {
PathwayStore
.startComplete({
participantId: this.props.participantId,
courseCode: this.props.courseCode
})
.then(this.fauxCompletion);
},
fauxCompletion() {
switch (this.getCourseType()){
case 'DOCUMENT':
var documentURL = this.state.course.getIn(['documentTag','documents',0,'url'])
window.location = `upload/view?objectKey=${documentURL}`;
break;
case 'VIDEO':
window.location.reload();
break;
}
},
onClose() {
if(this.props.onClose) {
return this.props.onClose();
}
//
// TODO: SOOPER HACK. Remove along with backbone
ReactDOM.unmountComponentAtNode(document.getElementById('Modal_content'));
},
onVideoFinish(){
this.setState({videoButtonDisabled: false});
},
getCourseType() {
// Documents and Videos are not poropertly
// supported through course.type
//
var type = this.state.course.get('type');
if (this.state.course.get('documentTag')) {
type = 'DOCUMENT';
}
if (this.state.course.get('videoTag')) {
type = 'VIDEO';
}
return type;
},
render() {
var {course, participation} = this.state;
if(!course || !participation) {
return <ModalView title="Loading..." loading={false}>
<Loader></Loader>
</ModalView>
}
var title = (
<span>{participation.get('firstName')} {participation.get('lastName')}'s Training Activity</span>
);
return (
<ModalView title={title} loading={this.state.fetchingCourse || this.state.fetchingParticipation}>
<div className="margin-bottom2">
<h3 className="hug-top">
<Icon modifier="inline" hexCode={course.get('courseIcon')}></Icon>
{course.get('workshopName')}
</h3>
<CourseActivityHistory {...this.state} courseType={this.getCourseType()}/>
</div>
{this.renderModalBody()}
<div className="ButtonBar right margin-top">
{this.renderCourseDetailsButton()}
<a className="Button Button-grey" onClick={this.onClose} data-js="close">Close</a>
{this.renderMainActionButton()}
</div>
</ModalView>
);
},
renderModalBody() {
return this[`render_${this.getCourseType()}`]();
},
render_E_LEARNING() {
return this.renderCourseStatusText(this.props.process, {
action: 'Go To Module'
});
},
render_LOCAL_QUIZ() {
return this.renderCourseStatusText(this.props.process, {
action: 'Go To Exam'
});
},
render_EVALUATION() {
var courseCode = this.state.course.get('courseCode');
var managerForm = <ManagerSelectForm name="managers" />;
var copy = <p>In order to become certified a Manager must complete a Service Advisor Performance Evaluation and deem you to be Competent. Please select a Manager from below to be notified of your desire to be evaluated.</p>;
if (courseCode === 'BT_EVAL' || courseCode === 'PT_EVAL') {
copy = <p>In order to become certified you need a TMCA Staff Member or a Dealer Manager to complete your evaluation and deem you to be competent. Please click request to notify a TMCA Staff Member to complete your evaluation.</p>;
managerForm = null;
}
return <div>
{copy}
<form ref="form" action="/careerPathway/managers" method="post">
<input type="hidden" name="courseCode" value={courseCode} />
<input type="hidden" name="careerPlanId" value={this.props.pathwayId} />
{managerForm}
</form>
</div>;
},
render_FACE_TO_FACE() {
var message;
switch(this.state.course.get('stream')) {
case 'PRO':
message = 'You have not yet successfully completed the courses from the previous stage, however, to continue to complete this course or module, click the Course Details button below.';
break;
case 'TECH':
message = `Unfortunately, ${this.state.participation.get('firstName')} is not yet eligible to be enrolled into this course as they have not completed the pre-requisites.`;
break;
}
if(!this.state.participation.get('eligible')) {
return <div className="InfoBox">{message}</div>;
}
var currentEnrollment = this.state.participation.get('history').find(item => item.get('process') === 'ENROLL');
return (
<div>
<RegistrationSingle {...this.props} onChange={this.onRequestChange} currentEnrollment={currentEnrollment}/>
</div>
);
},
render_DOCUMENT() {},
render_ACHIEVEMENT() {},
render_CERTIFICATION() {},
render_VIDEO() {
var view;
var {participation} = this.state;
if(participation.get('status')) {
view = `${participation.get('firstName')} completed this video. Please feel free to watch again to refresh your product knowledge.`;
} else {
view = 'Please watch the above video content. Once finished you will be able to Complete and return to your Product Plan.';
}
return (
<div>
<Video id={this.state.course.get('videoTag').get('videos').get(0).get('url')} onVideoFinish={this.onVideoFinish}/>
<div className="margin-top">{view}</div>
</div>
);
},
renderCourseStatusText(process, termOverride) {
var copy;
var {participation} = this.state;
var participationHistory = participation.get('history');
var firstName = participation.get('firstName');
var terms = _.defaults(termOverride, {
action: 'Go To Course'
});
if(participationHistory.get('0')){
process = participationHistory.getIn(['0','process']);
}
switch(process) {
case 'ATTENDED':
case 'COMPLETED':
copy = <p>{firstName} completed this course. If you wish to do a refresh, please {terms.action}.</p>;
break;
case 'CREDIT':
copy = <p>{firstName} was credited for this course. If you wish to do a refresh, please {terms.action}.</p>;
break;
case 'IN_PROGRESS':
copy = <p>The TRC recognises that {firstName} has launched this module previously. <br/>If the module was completed on the LMS, completion may take up to 36 hours to be displayed. To reattempt the module, please click {terms.action}.</p>;
break;
case 'FAILED':
copy = <p>Our records indicate {firstName} failed this course. To retry the module please {terms.action}.</p>;
break;
default:
copy = <p>Our records indicate {firstName} has not yet completed this course. Please {terms.action} to complete the course.</p>;
}
return <div>{copy}</div>;
},
renderCourseDetailsButton() {
if(this.state.course.get('viewableInList')) {
return <a className="Button Button-clear" href={`/#/course/${this.state.course.get('courseCode')}`} onClick={this.onClose}>Course Details</a>;
}
},
renderMainActionButton() {
var {participation, course} = this.state;
var button = null;
var buttonProps = {
className: 'Button',
disabled: !participation.get('eligible')
};
if(!this.props.actionable) {
return null;
}
switch (this.getCourseType()) {
case 'FACE_TO_FACE':
if(UserStore.is('ROLE_MANAGER')) {
button = <Button {...buttonProps} onClick={this.onRequestSubmit} disabled={!this.state.soId}>Enrol</Button>;
} else {
button = <Button {...buttonProps} onClick={this.onRequestSubmit} disabled={!(this.state.soId && this.state.manager)}>Request</Button>;
}
break;
case 'E_LEARNING':
button = <a {...buttonProps} href={`/#/course/${course.get('courseCode')}/launch`} onClick={this.onClose} data-js="close">Go To Module</a>;
break;
case 'LOCAL_QUIZ':
var href = `/careerPathway/${this.props.pathwayId}/assessment/quiz/${course.get('courseCode')}?participantId=${this.props.participantId}`;
if(!this.props.pathwayId || !course.get('courseCode') || participation.get('eligible') === false) {
button = <Button {...buttonProps} disabled={true}>Go To Exam</Button>;
} else {
button = <a {...buttonProps} href={href}>Go To Exam</a>;
}
break;
case 'EVALUATION':
button = <a {...buttonProps} onClick={this.onRequestEvaluation}>Request</a>;
break;
case 'DOCUMENT':
if(this.state.course.getIn(['documentTag','documents']).size !== 0){
button = <a {...buttonProps} onClick={this.startThenCompleteCourse}>View</a>;
}
break;
case 'VIDEO':
button = <Button {...buttonProps} disabled={this.state.videoButtonDisabled} onClick={this.startThenCompleteCourse}>Complete</Button>;
break;
}
return button;
}
});
module.exports = CourseActivityModal;