diff --git a/package.json b/package.json index 9d6a044dff..0ac6ceecb9 100644 --- a/package.json +++ b/package.json @@ -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" diff --git a/services/backend/oodikone2-backend/src/database/connection.js b/services/backend/oodikone2-backend/src/database/connection.js index 55128ac956..4ab25bb761 100644 --- a/services/backend/oodikone2-backend/src/database/connection.js +++ b/services/backend/oodikone2-backend/src/database/connection.js @@ -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 { diff --git a/services/oodikone2-frontend/src/components/CourseStatistics/SearchForm/index.jsx b/services/oodikone2-frontend/src/components/CourseStatistics/SearchForm/index.jsx index 0077c0befc..80bd969eaa 100644 --- a/services/oodikone2-frontend/src/components/CourseStatistics/SearchForm/index.jsx +++ b/services/oodikone2-frontend/src/components/CourseStatistics/SearchForm/index.jsx @@ -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' @@ -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) => { @@ -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 = () => { @@ -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 @@ -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) => { @@ -205,9 +251,10 @@ const mapStateToProps = (state) => { } } -export default connect(mapStateToProps, { +export default withRouter(connect(mapStateToProps, { getSemesters, getCourseStats, clearCourses, - findCoursesV2 -})(SearchForm) + findCoursesV2, + clearCourseStats +})(SearchForm)) diff --git a/services/oodikone2-frontend/src/components/PopulationStudents/index.jsx b/services/oodikone2-frontend/src/components/PopulationStudents/index.jsx index 791c75e39f..360946b4bd 100644 --- a/services/oodikone2-frontend/src/components/PopulationStudents/index.jsx +++ b/services/oodikone2-frontend/src/components/PopulationStudents/index.jsx @@ -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 => ( @@ -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: Labels:, + parent: true, + headerProps: { colSpan: nameColumns.length, style: { textAlign: 'right' } } + }, + ...mandatoryCourseLabels.map(e => ({ + key: e, + title: ( +