trc-client-core
Version:
The core of the TRC Client
282 lines (255 loc) • 9.39 kB
JSX
import React from 'react';
import _ from 'lodash';
import Reflux from 'reflux';
import StoreMixin from 'reflux-immutable/StoreMixin';
import moment from 'moment';
import {Link, History, State} from 'react-router';
// Stampy
import DataTable from 'bd-stampy/components/DataTable';
import {Tab, TabView, TabContent} from 'bd-stampy/components/Tabs';
// TRC
import CourseStore from 'trc-client-core/src/course/CourseStore';
import CourseActions from 'trc-client-core/src/course/CourseActions';
import Loader from 'trc-client-core/src/components/Loader';
import ModalConfirm from 'trc-client-core/src/Modal/ModalConfirm';
import ModalManager from 'trc-client-core/src/Modal/ModalManager';
import UserStore from 'trc-client-core/src/user/UserStore';
import CourseListQueryView from 'trc-client-core/src/course/CourseListQueryView';
import {
IconClipboard,
IconDocument,
IconPerson,
IconTelevision,
IconAward,
IconThumbsUp
} from 'trc-client-core/src/components/Icons';
import {
E_LEARNING,
FACE_TO_FACE,
LOCAL_QUIZ,
DOCUMENT,
ACHIEVEMENT,
CERTIFICATION
} from 'trc-client-core/src/constants/CourseType';
var CoursesAdminView = React.createClass({
displayName: 'CoursesAdminView',
contextTypes: {
location: React.PropTypes.object
},
mixins: [
require('bd-stampy/mixins/FormMixin'),
Reflux.listenTo(CourseStore, 'onStoreChange'),
StoreMixin,
History,
State
],
getStoreState() {
return {
courses: CourseStore.get('courses')
};
},
componentDidMount() {
CourseActions.fetchCourses({onlyViewable: false});
},
FormMixin_initialFormData(nextState) {
nextState.formData = _.defaults(this.context.location.query, {
type: 'ALL',
stream: 'ALL',
departmentCategory: 'ALL'
});
return nextState;
},
onDelete(id) {
ModalManager.showModal(ModalConfirm, {
title: 'Delete Course',
yes: 'Delete',
message: 'Are you sure you want to delete this course?',
onYes: () => {
CourseStore.course.del(id).then(
() => {
CourseActions.fetchCourses({onlyViewable: false});
this.history.pushState(null, '/course', this.context.location.query);
}
);
}
});
},
onPublish(course) {
ModalManager.showModal(ModalConfirm, {
title: 'Publish Course',
yes: 'Publish',
message: `Are you sure you want to publish this course?`,
onYes: () => {
CourseActions.publish(course);
}
});
},
onChange(e, details) {
var param = {};
param[details.key] = details.value;
this.history.replaceState(null, '/course', _.defaults(param, this.context.location.query));
this.FormMixin_onFormChange(e, details);
},
onTabChange(e) {
this.history.replaceState(null, '/course', {tab: e});
},
onPagingate(e, page) {
this.history.replaceState(null, '/course', {
tab: this.context.location.query.tab,
page: page
});
},
filterMissingCourses() {
return this.state.courses.toJS().filter((data) => {
return [
'workshopName',
'abbreviatedName',
'attendance',
'courseCode',
'courseIcon',
'departmentCategory',
'duration',
'learningOutcomes',
'overview'
].some(prop => {
return !(data[prop] && /\S/.test(data[prop]));
});
});
},
render() {
if(!this.state.courses) {
return null;
}
var qaCourses = this.filterMissingCourses();
return (
<div>
<h1>Courses</h1>
<CourseListQueryView onChange={this.onChange} value={this.state.formData}/>
<div className="padding flush-right right">
<Link to="/course/new" className="Button Button-edit">New Course</Link>
</div>
<TabView onChange={this.onTabChange} transition={false} defaultTab={parseInt(this.context.location.query.tab || 1)}>
<Tab>All Courses</Tab>
<TabContent>
{this.renderErrors(this.state.error)}
{this.renderCourseTable(this.state.courses.toJS())}
</TabContent>
<Tab onClick={this.tabClick}>{`QA (${qaCourses.length})`}</Tab>
<TabContent>
{this.renderCourseTable(qaCourses)}
</TabContent>
</TabView>
</div>
);
},
renderQueryView(key) {
return <CourseListQueryView key={key} onChange={this.onChange} value={this.state.formData}/>;
},
renderErrors(error) {
if(error) {
return <div className="InfoBox InfoBox-error">
{error.errorMessage}
</div>;
}
},
renderCourseTable(courses) {
var pageAmmount = 50;
var currentPage = parseInt(this.context.location.query.page, 10) || 0;
if(!courses) {
return <Loader></Loader>;
}
var filtered = courses.filter(CourseStore.filterCourses(this.state.formData));
var tableSchema = [{
heading: 'Name',
filter: 'workshopName',
width: '30%',
render: (item) => <Link to={`/course/${item.courseCode}`} className="link">{item.workshopName}</Link>
}, {
heading: 'Course Code',
filter: 'courseCode',
width: '15%',
render: (item) => item.courseCode || ' - '
}, {
heading: 'Date Modified',
filter: 'lastModified',
render: (item) => moment(new Date(item.lastModified || 0)).format('YYYY-MM-DD')
}, {
heading: 'Stream',
filter: 'stream',
render: (item) => _.startCase(item.stream)
}, {
heading: 'Type',
filter: 'type',
render: this.renderCourseStatus
}, {
heading: 'Quality',
filter: 'type',
render: item => {
var values = _(item).values();
var filled = values.filter(str => !(String(str).length === 0 || !String(str).trim()));
var decimal = filled.value().length / values.value().length
return <span className={(decimal <= 0.8) ? 't-red' : ''}>{`${Math.floor(decimal * 100)}%`}</span>
}
}, {
heading: 'Actions',
render: this.renderActions,
width: '15%'
}];
return <DataTable
schema={tableSchema}
data={filtered}
pagination={true}
paginationLength={pageAmmount}
paginationPage={currentPage}
onPagingate={this.onPagingate}
modifier="data"
/>;
},
renderActions(dd) {
var test;
var badgeColor = (dd.draft) ? 'Button-green' : '';
var publish = <a key="publish" className={badgeColor + " Button Button-small w100"} onClick={this.onPublish.bind(null, dd)}>Publish</a>;
var deleteButton = <a key="delete" className="Button Button-small Button-grey w100" onClick={this.onDelete.bind(this, dd.id)}>Delete</a>;
if(dd.type === 'E_LEARNING' && dd.eLearningTag.moduleId) {
test = <a key="test" className="Button Button-small Button-grey w100" href={`${UserStore.get('elearningServer')}tester/${dd.eLearningTag.moduleId}`}>Test</a>;
}
// You cannot publish an elearning course that hasnt been tested
if(!dd.draft || (dd.type === 'E_LEARNING' && !dd.eLearningTag.testResult) && UserStore.isnt('ROLE_MEGA_ADMIN')) {
publish = null;
}
// You cannot delte published courses
if(!dd.draft) {
deleteButton = null;
}
return <div>
<Link key="edit" to={`/course/${dd.courseCode}/edit`} className="Button Button-small Button-edit w100">Edit</Link>
{deleteButton}
{test}
{publish}
</div>;
},
renderCourseStatus(dd) {
var className;
if(dd.type === 'E_LEARNING') {
className = (dd.eLearningTag.testResult) ? 't-green' : 't-red';
if(!dd.eLearningTag.moduleId) {
className = '';
}
}
switch(dd.type) {
case E_LEARNING:
return <IconTelevision className={className} />;
case FACE_TO_FACE:
return <IconPerson className={className} />;
case LOCAL_QUIZ:
return <IconClipboard className={className} />;
case DOCUMENT:
return <IconDocument className={className} />;
case ACHIEVEMENT:
return <IconThumbsUp className={className} />;
case CERTIFICATION:
return <IconAward className={className} />;
}
}
});
module.exports = CoursesAdminView;