trc-client-core
Version:
The core of the TRC Client
363 lines (300 loc) • 11.9 kB
JSX
import { Component, PropTypes } from 'react';
import { Link } from 'react-router';
import { connect } from 'react-redux';
// actions
import {
learningPlanRequestGet,
learningPlanRequestCreate,
learningPlanRequestUpdate,
learningPlanRequestDelete
} from 'trc-client-core/src/learningPlan/LearningPlanActions.js';
import { requestCourseList } from 'trc-client-core/src/course/CourseActions';
import { jobPositionRequest } from 'trc-client-core/src/participant/ParticipantActions';
import {
LEARNING_PLAN_GET_FETCH,
LEARNING_PLAN_GET_ERROR,
LEARNING_PLAN_CREATE_FETCH,
LEARNING_PLAN_CREATE_ERROR,
LEARNING_PLAN_UPDATE_FETCH,
LEARNING_PLAN_UPDATE_ERROR,
LEARNING_PLAN_DELETE_FETCH,
LEARNING_PLAN_DELETE_ERROR
} from 'trc-client-core/src/constants/ActionTypes';
// components
import Page from 'trc-client-core/src/components/Page';
import Loader from 'trc-client-core/src/components/Loader';
import ErrorMessage from 'trc-client-core/src/components/ErrorMessage';
import AutoRequest from 'trc-client-core/src/components/AutoRequest';
import Button from 'bd-stampy/components/Button';
import ModalManager from 'trc-client-core/src/Modal/ModalManager';
import ModalConfirm from 'trc-client-core/src/Modal/ModalConfirm';
import LoadingActions from 'trc-client-core/src/global/LoadingActions';
import AdminLearningPlanForm from 'trc-client-core/src/admin/AdminLearningPlanForm';
//
// AdminLearningPlanEditView class
//
class AdminLearningPlanEditView extends Component {
//
// lifecycle methods
//
initialState() {
return {
created: false,
copied: false,
deleted: false,
saveError: false
};
}
constructor(props) {
super(props);
this.state = this.initialState();
}
componentWillMount() {
this.props.dispatch(jobPositionRequest());
this.props.dispatch(requestCourseList());
}
componentWillReceiveProps(newProps) {
// reset state if a new learning plan's info is to be shown in the form
if(this.loadsFromExisting(newProps)) {
this.setState(this.initialState());
}
}
//
// helpers
//
currentLearningPlan() {
// gets the current learning plan object (an immutable map), or null if none correspond to current learningPlanId prop
return this.props.learningPlans.get(this.props.params.learningPlanId);
}
loadsFromExisting(props = this.props) {
// returns true if the form loads from an existing record, false if the form starts blank
return !!props.params.learningPlanId; // true if a learningPlanId exists
}
savesToExisting(props = this.props) {
// returns true if the form saves to an existing record, false if the form is to create a new record on save
return !!props.route.savesToExisting; // true if savesToExisting is true on the route
}
copiesExisting(props = this.props) {
return this.loadsFromExisting() && !this.savesToExisting();
}
getInitialFormValues(currentLearningPlan) {
if(!currentLearningPlan) {
return {
brand: "Toyota"
};
}
var plan = currentLearningPlan.toJS();
return plan;
}
//
// event and click handlers
//
handleSubmit(values, dispatch) {
this.saveLearningPlan(values);
}
handleResetClick(resetForm) {
ModalManager.showModal(ModalConfirm, {
title: 'Are you sure you want to reset?',
message: 'Are you sure you want to reset? Any changes since your last save will be lost.',
yes: 'Yes I\'m sure',
onYes: resetForm,
no: 'Cancel'
});
}
handleCloseClick(ee, dirty = false) {
ee.preventDefault();
if(dirty) {
ModalManager.showModal(ModalConfirm, {
title: 'Unsaved changes',
message: 'You may have unsaved changes, are you sure you want to leave this page?',
yes: 'Leave page',
onYes: this.closeLearningPlan.bind(this),
no: 'Cancel'
});
} else {
this.closeLearningPlan();
}
}
handleDeleteClick(ee) {
ee.preventDefault();
ModalManager.showModal(ModalConfirm, {
title: 'Delete learning plan',
message: 'Are you sure you want to delete this? This action cannot be undone',
yes: 'Yes I\'m sure',
onYes: this.deleteLearningPlan.bind(this),
no: 'Cancel'
});
}
//
// form actions
//
closeLearningPlan() {
this.props.history.push('/admin/learning-plans');
}
saveLearningPlan(learningPlanObject) {
const { learningPlanId } = this.props.params;
if(this.copiesExisting()) {
this.props.dispatch(learningPlanRequestUpdate(learningPlanId,learningPlanObject)).then(
(data) => {
this.setState({
copied: data.payload.careerPlanId
});
}
);
} else if(this.savesToExisting()) {
LoadingActions.startLoading();
this.props.dispatch(learningPlanRequestUpdate(learningPlanId,learningPlanObject)).then(
(data) => {
if(data.type == LEARNING_PLAN_UPDATE_ERROR) {
LoadingActions.flashMessage('failure long', 'An error occurred. Your work is not yet saved.\n'+data.payload.message, 5000);
} else {
LoadingActions.flashMessage('success', 'Save complete');
}
}
);
} else {
this.props.dispatch(learningPlanRequestCreate(learningPlanObject)).then(
(data) => {
this.setState({
created: data.payload.careerPlanId
});
}
);
}
}
deleteLearningPlan() {
const { learningPlanId } = this.props.params;
LoadingActions.startLoading();
this.props.dispatch(learningPlanRequestDelete(learningPlanId)).then(
(data) => {
if(data.type == LEARNING_PLAN_DELETE_ERROR) {
LoadingActions.flashMessage('failure long', 'An error occurred. This learning plan is not yet deleted.\n'+data.payload.message, 5000);
} else {
LoadingActions.clearAll();
this.setState({
deleted: true
});
}
}
);
}
//
// render
//
render() {
return (
<Page title="Learning Plan Editor">
<div>
{this.renderEditor()}
</div>
</Page>
);
}
renderEditor() {
const { params: { learningPlanId }, fetching, saving, deleting, error, handleSubmit, courses, jobPositions } = this.props;
const { created, copied, deleted } = this.state;
var showErrorPage = false;
if(fetching) {
return <Loader />;
} else if(error) {
// if there's an error we'll usually want to show an error page, except if the error happens on save
showErrorPage = true;
} else if (created) {
return (
<div>
<h2 className="hug-top">Learning plan created</h2>
<p><Button onClick={this.handleCloseClick.bind(this)}>Back to list</Button> <Link to={`/admin/learning-plans/${created}/edit`} activeClassName="is-active" className="Button Button-edit">Edit learning plan</Link></p>
</div>
);
} else if (copied) {
return (
<div>
<h2 className="hug-top">Learning plan copied</h2>
<p><Button onClick={this.handleCloseClick.bind(this)}>Back to list</Button> <Link to={`/admin/learning-plans/${copied}/edit`} activeClassName="is-active" className="Button Button-edit">Edit learning plan</Link></p>
</div>
);
} else if(deleted) {
return (
<div>
<h2 className="hug-top">Learning plan deleted</h2>
<p><Button onClick={this.handleCloseClick.bind(this)}>Back to list</Button></p>
</div>
);
}
var title, id, plan;
// if trying to display a learning plan, get learning plan details
if(learningPlanId) {
plan = this.currentLearningPlan();
if(!plan) {
// learning plan at this URL doesn't exist
return (
<div>
<h2 className="hug-top">No learning plan found at this URL</h2>
<p><Button onClick={this.handleCloseClick.bind(this)}>Back to list</Button></p>
</div>
);
}
var planJS = plan.toJS();
title = planJS.displayName || "Unnamed learning plan";
id = planJS.careerPlanId;
showErrorPage = false;
} else {
// no learning plan id means this must be a new one
title = "New learning plan";
}
if(this.copiesExisting()) {
title = "New copy of " + title;
}
if(showErrorPage) {
return <ErrorMessage code={400} message={error.message} />;
}
var initialValues = this.getInitialFormValues(plan);
return (
<div>
<h1 className="hug-top">{title}</h1>
<AdminLearningPlanForm
onSubmit={this.handleSubmit}
savesToExisting={this.savesToExisting()}
copiesExisting={this.copiesExisting()}
isSaving={saving}
isDeleting={deleting}
onCloseClick={this.handleCloseClick.bind(this)}
onDeleteClick={this.handleDeleteClick.bind(this)}
onResetClick={this.handleResetClick.bind(this)}
onSubmitForm={this.handleSubmit.bind(this)}
initialValues={initialValues}
courses={courses}
jobPositions={jobPositions} />
</div>
);
}
}
AdminLearningPlanEditView.propTypes = {
learningPlanEdit: PropTypes.object,
fetching: PropTypes.bool,
saving: PropTypes.bool,
deleting: PropTypes.bool,
error: PropTypes.object
};
const autoRequest = AutoRequest(['params.learningPlanId'], (props) => {
// get learning plan info
if(props.params.learningPlanId) {
props.dispatch(learningPlanRequestGet(props.params.learningPlanId));
}
});
const connectWithAdminLearningPlan = connect(
(state) => ({
learningPlans: state.learningPlan.get('collection'),
fetching: state.async.get( LEARNING_PLAN_GET_FETCH ),
saving: state.async.get( LEARNING_PLAN_CREATE_FETCH )
|| state.async.get( LEARNING_PLAN_UPDATE_FETCH ),
deleting: state.async.get( LEARNING_PLAN_DELETE_FETCH ),
error: state.async.get( LEARNING_PLAN_GET_ERROR )
|| state.async.get( LEARNING_PLAN_CREATE_ERROR )
|| state.async.get( LEARNING_PLAN_UPDATE_ERROR )
|| state.async.get( LEARNING_PLAN_DELETE_ERROR ),
courses: state.course.get('collection'),
jobPositions: state.participant.get('jobPositions').toJS()
})
);
export default connectWithAdminLearningPlan(autoRequest(AdminLearningPlanEditView));