<commit_before>import React from 'react'
import {Link, State} from 'react-router'
import {isObject, chain, map} from 'lodash'

import {toPrettyTerm} from 'sto-helpers'
import queryCourseDatabase from '../helpers/queryCourseDatabase'
import Course from './course'
import stickyfill from '../helpers/initStickyfill'

let SearchButton = React.createClass({
	mixins: [State],

	propTypes: {
		student: React.PropTypes.object.isRequired,
		toggle: React.PropTypes.func.isRequired,
	},

	componentDidMount() {
		stickyfill.add(this.getDOMNode())
	},

	componentWillUnmount() {
		stickyfill.remove(this.getDOMNode())
	},

	getInitialState() {
		return {
			isQuerying: false,
			hasQueried: false,
			results: [],
			queryString: '',
			query: null,
		}
	},

	onSubmit() {
		this.query(this.state.queryString)
	},

	onChange(evt) {
		this.setState({queryString: evt.target.value})
	},

	onKeyDown(evt) {
		if (evt.keyCode == 13) {
			this.onSubmit()
		}
	},

	processQueryResults([results, startQueryTime]=[]) {
		console.log('results', results)

		let searchResults = chain(results)
			.sortBy(c => `${c.deptnum}${c.sect || ''}`) // Sort the results
			.groupBy('term') // Group them by term
			.pairs() // Turn the object into an array of pairs
			// Sort the result arrays by the first element, the term,
			// because object keys don't have an implicit sort.
			.sortBy(group => group[0])
			.reverse() // reverse it, so the most recent is at the top
			.flatten() // flatten once, to merge the [date, courses] arrays
			.flatten() // then flatten once more, to raise the courses into the array
			.value()

		console.log('search results', searchResults)
		let endQueryTime = present()
		console.info(`query took ${(endQueryTime - startQueryTime)}ms.`)

		let startTime = present()
		let courseObjects = map(searchResults, (courseOrTerm) => {
			if (!isObject(courseOrTerm)) {
				let prettyTerm = toPrettyTerm(courseOrTerm)

				return React.createElement('li',
					{key: prettyTerm, className: 'course-group'},
					prettyTerm)
			}
			return React.createElement('li',
				{key: courseOrTerm.clbid},
				React.createElement(Course, {info: courseOrTerm}))
		})

		let endTime = present()
		console.info(`element creation took an additional ${(endTime - startTime)}ms.`)

		this.setState({results: courseObjects, hasQueried: true, query: null})
	},

	query(searchQuery) {
		if (searchQuery.length === 0 || this.state.query)
			return

		this.setState({results: [], hasQueried: false})
		let startQueryTime = present()

		let query = queryCourseDatabase(searchQuery)
			.then(results => [results, startQueryTime])
			.then(this.processQueryResults)

		this.setState({query})
	},

	render() {<commit_msg>Catch errors from queryCourseDatabase<commit_after>import React from 'react'
import {Link, State} from 'react-router'
import {isObject, chain, map} from 'lodash'

import {toPrettyTerm} from 'sto-helpers'
import queryCourseDatabase from '../helpers/queryCourseDatabase'
import Course from './course'
import stickyfill from '../helpers/initStickyfill'

let SearchButton = React.createClass({
	mixins: [State],

	propTypes: {
		student: React.PropTypes.object.isRequired,
		toggle: React.PropTypes.func.isRequired,
	},

	componentDidMount() {
		stickyfill.add(this.getDOMNode())
	},

	componentWillUnmount() {
		stickyfill.remove(this.getDOMNode())
	},

	getInitialState() {
		return {
			isQuerying: false,
			hasQueried: false,
			results: [],
			queryString: '',
			query: null,
		}
	},

	onSubmit() {
		this.query(this.state.queryString)
	},

	onChange(evt) {
		this.setState({queryString: evt.target.value})
	},

	onKeyDown(evt) {
		if (evt.keyCode == 13) {
			this.onSubmit()
		}
	},

	processQueryResults([results, startQueryTime]=[]) {
		console.log('results', results)

		let searchResults = chain(results)
			.sortBy(c => `${c.deptnum}${c.sect || ''}`) // Sort the results
			.groupBy('term') // Group them by term
			.pairs() // Turn the object into an array of pairs
			// Sort the result arrays by the first element, the term,
			// because object keys don't have an implicit sort.
			.sortBy(group => group[0])
			.reverse() // reverse it, so the most recent is at the top
			.flatten() // flatten once, to merge the [date, courses] arrays
			.flatten() // then flatten once more, to raise the courses into the array
			.value()

		console.log('search results', searchResults)
		let endQueryTime = present()
		console.info(`query took ${(endQueryTime - startQueryTime)}ms.`)

		let startTime = present()
		let courseObjects = map(searchResults, (courseOrTerm) => {
			if (!isObject(courseOrTerm)) {
				let prettyTerm = toPrettyTerm(courseOrTerm)

				return React.createElement('li',
					{key: prettyTerm, className: 'course-group'},
					prettyTerm)
			}
			return React.createElement('li',
				{key: courseOrTerm.clbid},
				React.createElement(Course, {info: courseOrTerm}))
		})

		let endTime = present()
		console.info(`element creation took an additional ${(endTime - startTime)}ms.`)

		this.setState({results: courseObjects, hasQueried: true, query: null})
	},

	query(searchQuery) {
		if (searchQuery.length === 0 || this.state.query)
			return

		this.setState({results: [], hasQueried: false})
		let startQueryTime = present()

		let query = queryCourseDatabase(searchQuery)
			.then(results => [results, startQueryTime])
			.then(this.processQueryResults)
			.catch(err => console.error(err))
			.done()

		this.setState({query})
	},

	render() {
{'fraction_non_alphanumeric': 0.14309210526315788, 'fraction_numerical': 0.0014619883040935672, 'mean_word_length': 3.998173515981735, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2856989', 'n_tokens_mistral': 1962, 'n_tokens_neox': 1738, 'n_words': 440}