Skip to content

Commit

Permalink
Merge pull request #979 from UniversityOfHelsinkiCS/trunk
Browse files Browse the repository at this point in the history
course statistics url
  • Loading branch information
sasumaki authored Jun 4, 2019
2 parents 3b16525 + e49f986 commit e5938d5
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 37 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"scripts": {
"cypress:open": "CYPRESS_baseUrl=http://localhost:8081 cypress open",
"cypress:run": "CYPRESS_baseUrl=http://localhost:8081 cypress run --config video=false -P ./",
"cypress:record": "cypress run --config videoUploadOnPasses=false --record -P ./",
"cypress:record": "cypress run --config videoUploadOnPasses=false -P ./",
"concurrently": "concurrently",
"test": "./run_all_tests.sh",
"test_services": "./run_service_tests.sh"
Expand Down
13 changes: 4 additions & 9 deletions services/backend/oodikone2-backend/src/database/connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,16 @@ const conf = require('../conf-backend')
const sequelize = new Sequelize(conf.DB_URL, {
schema: conf.DB_SCHEMA,
logging: false,
operatorsAliases: false,
dialectOptions: {
prependSearchPath: true
}
operatorsAliases: false
})
sequelize.query(`SET SESSION search_path to ${conf.DB_SCHEMA}`)

const sequelizeKone = new Sequelize(conf.DB_URL, {
schema: conf.DB_SCHEMA_KONE,
logging: false,
operatorsAliases: false,
searchPath: conf.DB_SCHEMA_KONE,
dialectOptions: {
prependSearchPath: true
}
operatorsAliases: false
})
sequelizeKone.query(`SET SESSION search_path to ${conf.DB_SCHEMA_KONE}`) // See https://github.com/sequelize/sequelize/issues/10875

const runMigrations = async () => {
try {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import React, { Component } from 'react'
import { Segment, Header, Form } from 'semantic-ui-react'
import { connect } from 'react-redux'
import { withRouter } from 'react-router'
import qs from 'query-string'
import { func, arrayOf, shape, bool } from 'prop-types'
import { getSemesters } from '../../../redux/semesters'
import { clearCourses, findCoursesV2 } from '../../../redux/coursesearch'
import { getCourseStats } from '../../../redux/coursestats'
import { getCourseStats, clearCourseStats } from '../../../redux/coursestats'
import AutoSubmitSearchInput from '../../AutoSubmitSearchInput'
import CourseTable from '../CourseTable'
import { getCourseSearchResults } from '../../../selectors/courses'
Expand All @@ -30,8 +32,22 @@ class SearchForm extends Component {
}

componentDidMount() {
this.props.getSemesters()
this.props.clearCourses()
const { location } = this.props
if (location.search) {
console.log(location.search)
this.fetchStatisticsFromUrlParams()
} else {
this.props.getSemesters()
this.props.clearCourses()
}
}

componentDidUpdate(prevProps) {
const { location } = this.props
const queryParamsChanged = prevProps.location.search !== this.props.location.search
if (location.search && queryParamsChanged) {
this.fetchStatisticsFromUrlParams()
}
}

onSelectCourse = (course) => {
Expand Down Expand Up @@ -69,7 +85,36 @@ class SearchForm extends Component {
separate
}

await this.props.getCourseStats(params)
// await this.props.getCourseStats(params)
this.pushQueryToUrl(params)
}

fetchStatisticsFromUrlParams() {
const query = this.parseQueryFromUrl()
this.setState({ ...query, selectedcourses: query.courseCodes })
this.props.getCourseStats(query)
}

pushQueryToUrl = (query) => {
const { history } = this.props
const { courseCodes, ...rest } = query
const queryObject = { ...rest, courseCodes: JSON.stringify(courseCodes) }
const searchString = qs.stringify(queryObject)
history.push({ search: searchString })
}

parseQueryFromUrl = () => {
const { location } = this.props
const { courseCodes, fromYear, toYear, separate, ...rest } = qs.parse(location.search)
const query = {
...this.state.INITIAL,
...rest,
courseCodes: JSON.parse(courseCodes),
fromYear: JSON.parse(fromYear),
toYear: JSON.parse(toYear),
separate: JSON.parse(separate)
}
return query
}

fetchCourses = () => {
Expand Down Expand Up @@ -103,7 +148,6 @@ class SearchForm extends Component {
coursename,
coursecode
} = this.state

const courses = matchingCourses.filter(c => !selectedcourses[c.code])

const disabled = (!fromYear || Object.keys(selectedcourses).length === 0) || isLoading
Expand Down Expand Up @@ -187,7 +231,9 @@ SearchForm.propTypes = {
matchingCourses: arrayOf(shape({})).isRequired,
years: arrayOf(shape({})).isRequired,
isLoading: bool.isRequired,
coursesLoading: bool.isRequired
coursesLoading: bool.isRequired,
history: shape({}).isRequired,
location: shape({}).isRequired
}

const mapStateToProps = (state) => {
Expand All @@ -205,9 +251,10 @@ const mapStateToProps = (state) => {
}
}

export default connect(mapStateToProps, {
export default withRouter(connect(mapStateToProps, {
getSemesters,
getCourseStats,
clearCourses,
findCoursesV2
})(SearchForm)
findCoursesV2,
clearCourseStats
})(SearchForm))
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,12 @@ class PopulationStudents extends Component {

const priorityText = (studyRights) => {
const codes = this.studyrightCodes(studyRights, 'prioritycode')
return codes.map(code => PRIORITYCODE_TEXTS[code] ? PRIORITYCODE_TEXTS[code] : code).join(', ') // eslint-disable-line
return codes.map(code => (PRIORITYCODE_TEXTS[code] ? PRIORITYCODE_TEXTS[code] : code)).join(', ')
}

const extentCodes = (studyRights) => {
const codes = this.studyrightCodes(studyRights, 'extentcode')
return codes.join(', ') // eslint-disable-line
return codes.join(', ')
}

const studytrack = studyrights => (
Expand Down Expand Up @@ -290,22 +290,29 @@ class PopulationStudents extends Component {
['asc', 'asc']
)

const labelColumns = []
if (mandatoryCourseLabels.reduce((acc, e) => acc + e.length, 0) > 0) {
labelColumns.push(
{
key: 'general',
title: <b>Labels:</b>,
parent: true,
headerProps: { colSpan: nameColumns.length, style: { textAlign: 'right' } }
},
...mandatoryCourseLabels.map(e => ({
key: e,
title: (
<div style={{ overflowX: 'hidden' }}><div style={{ width: 0 }}>{e}</div></div>
),
parent: true,
headerProps: { colSpan: labelToMandatoryCourses[e].length, width: labelToMandatoryCourses[e].length, title: e }
}))
)
}

const mandatoryCourseColumns = [
...nameColumns,
...(mandatoryCourseLabels.reduce((acc, e) => acc + e.length, 0) > 0) ? [{
key: 'general',
title: <b>Labels:</b>,
parent: true,
headerProps: { colSpan: nameColumns.length, style: { textAlign: 'right' } }
}] : [],
...mandatoryCourseLabels.map(e => ({
key: e,
title: (
<div style={{ overflowX: 'hidden' }}><div style={{ width: 0 }}>{e}</div></div>
),
parent: true,
headerProps: { colSpan: labelToMandatoryCourses[e].length, width: labelToMandatoryCourses[e].length, title: e }
})),
...labelColumns,
..._.flatten(mandatoryCourseLabels.map(e => _.sortBy(
labelToMandatoryCourses[e],
[(m) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@ import { func, shape, string, boolean, arrayOf, integer } from 'prop-types'
import { connect } from 'react-redux'
import { Segment, Table, Icon } from 'semantic-ui-react'
import { isEmpty, sortBy } from 'lodash'
import moment from 'moment'
import qs from 'query-string'
import { withRouter } from 'react-router-dom'
import { getStudent, removeStudentSelection, resetStudent } from '../../redux/students'
import StudentInfoCard from '../StudentInfoCard'
import CreditAccumulationGraph from '../CreditAccumulationGraph'
import SearchResultTable from '../SearchResultTable'
import { byDateDesc, reformatDate, getTextIn } from '../../common'
import { clearCourseStats } from '../../redux/coursestats'


class StudentDetails extends Component {
componentDidMount() {
Expand All @@ -26,6 +30,16 @@ class StudentDetails extends Component {
}
}

pushQueryToUrl = (query) => {
const { history } = this.props
const { courseCodes, ...rest } = query
const queryObject = { ...rest, courseCodes: JSON.stringify(courseCodes) }
const searchString = qs.stringify(queryObject)
this.props.clearCourseStats()
history.push('/coursestatistics/')
history.push({ search: searchString })
}

renderCreditsGraph = () => {
const { translate, student } = this.props
return (
Expand Down Expand Up @@ -60,11 +74,13 @@ class StudentDetails extends Component {
} else {
icon = <Icon name="circle outline" color="red" />
}
const year = -(moment(new Date('1.1.1950')).diff(new Date('2004'), 'years') - 1) // :D
return [
reformatDate(date, 'DD.MM.YYYY'),
`${isStudyModuleCredit ? `${getTextIn(course.name, language)} [Study Module]` : getTextIn(course.name, language)} (${course.code})`,
<div>{icon}{grade}</div>,
credits
credits,
<Icon name="arrow up" onClick={() => this.pushQueryToUrl({ courseCodes: [course.code], separate: false, fromYear: year, toYear: year })} />
]
})
return (
Expand Down Expand Up @@ -204,6 +220,7 @@ StudentDetails.propTypes = {
removeStudentSelection: func.isRequired,
studentNumber: string,
translate: func.isRequired,
clearCourseStats: func.isRequired,
student: shape({
courses: arrayOf(shape({
course: shape({
Expand Down Expand Up @@ -235,6 +252,7 @@ const mapStateToProps = ({ students, settings }) => ({
})
const mapDispatchToProps = dispatch => ({
removeStudentSelection: () => dispatch(removeStudentSelection()),
clearCourseStats: () => dispatch(clearCourseStats()),
resetStudent: () => dispatch(resetStudent()),
getStudent: studentNumber =>
dispatch(getStudent(studentNumber))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ class StudyProgrammeSelector extends Component {
getRowKey={programme => programme.code}
getRowProps={programme => ({ onClick: () => this.props.handleSelect(programme.code), style: { cursor: 'pointer' } })}
data={studyprogrammes}
defaultdescending
/>
)
}
Expand Down

0 comments on commit e5938d5

Please sign in to comment.