Home Identifier Source Repository

src/components/course.js

import React, {Component, PropTypes} from 'react'
import {DragSource} from 'react-dnd'
import cx from 'classnames'
import compact from 'lodash/array/compact'
import filter from 'lodash/collection/filter'
import isNull from 'lodash/lang/isNull'
import map from 'lodash/collection/map'

import itemTypes from '../models/item-types'
import Schedule from '../models/schedule'
import Student from '../models/student'

import List from './list'
import DetailedCourse from './detailed-course'
import BasicCourse from './basic-course'

import './course.scss'

// Implements the drag source contract.
const courseSource = {
	beginDrag(props) {
		const scheduleId = props.schedule ? props.schedule.id : null
		return {
			fromSchedule: scheduleId !== null,
			fromSearch: scheduleId === null,
			clbid: props.course.clbid,
			groupid: props.course.groupid,
			fromScheduleID: scheduleId,
		}
	},
}

// Specifies the props to inject into your component.
function collect(connect, monitor) {
	return {
		connectDragSource: connect.dragSource(),
		isDragging: monitor.isDragging(),
	}
}

class Course extends Component {
	static propTypes = {
		conflicts: PropTypes.array,
		connectDragSource: PropTypes.func.isRequired,  // react-dnd
		course: PropTypes.object.isRequired,
		index: PropTypes.number,
		isDragging: PropTypes.bool.isRequired,  // react-dnd
		schedule: PropTypes.instanceOf(Schedule),
		student: PropTypes.instanceOf(Student),
	}

	static defaultProps = {
		conflicts: [],
	}

	constructor() {
		super()
		this.state = {isOpen: false}
	}

	toggleExpanded = () => {
		this.setState({isOpen: !this.state.isOpen})
	}

	render() {
		// console.log('Course#render')
		let InnerCourse = this.state.isOpen
			? DetailedCourse
			: BasicCourse

		let warnings = this.props.conflicts[this.props.index || 0]
		let hasWarnings = compact(warnings).length

		const validWarnings = filter(warnings, w => !isNull(w) && w.warning === true)
		const warningEls = map(validWarnings, (w, index) =>
			<span className={w.className} key={index}>{w.msg}</span>)

		let classSet = cx('course', {
			expanded: this.state.isOpen,
			'has-warnings': hasWarnings,
			'is-dragging': this.props.isDragging,
		})

		return this.props.connectDragSource(
			<article className={classSet}>
				<InnerCourse {...this.props} onClick={this.toggleExpanded}>
					{warningEls.length
						? <List type='inline' className='warnings'>{warningEls}</List>
						: null}
				</InnerCourse>
			</article>
		)
	}
}

export default DragSource(itemTypes.COURSE, courseSource, collect)(Course)