Skip to content

Commit

Permalink
Merge pull request #1138 from UniversityOfHelsinkiCS/trunk
Browse files Browse the repository at this point in the history
Game changing hook 🥊
  • Loading branch information
esakemp authored Jul 18, 2019
2 parents e68a79c + c8375bf commit 8e6491b
Show file tree
Hide file tree
Showing 7 changed files with 287 additions and 235 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,6 @@ class CourseStatsCounter {
if (passed) {
if (!improved && !this.students.passed[studentnumber]) {
this.markPassedSemester(semester)
} else if (studentnumber === '012327001') {
this.markPassedSemester(semester)
}
this.markPassingGrade(studentnumber)
} else if (improved) {
Expand Down
37 changes: 37 additions & 0 deletions services/oodikone2-frontend/src/common/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { useState, useEffect } from 'react'
import moment from 'moment'
import jwtDecode from 'jwt-decode'
import Datetime from 'react-datetime'
import { uniqBy, filter } from 'lodash'
import pathToRegexp from 'path-to-regexp'
import qs from 'query-string'
import { API_DATE_FORMAT, DISPLAY_DATE_FORMAT, TOKEN_NAME } from '../constants'
import toskaLogo from '../assets/toska.png'
import irtomikko from '../assets/irtomikko.png'
Expand Down Expand Up @@ -213,3 +215,38 @@ export const getTextIn = (texts, language) => {
}
return null
}

export const useTabs = (id, initialTab, { location, replace }) => {
const [tab, setTab] = useState(null)
const [didMount, setDidMount] = useState(false)

const pushToUrl = (newTab) => {
replace({
pathname: location.pathname,
search: qs.stringify({ ...qs.parse(location.search), [id]: newTab })
})
}

useEffect(() => {
const params = qs.parse(location.search)
let queryTab = params[id]
if (queryTab === undefined) {
setTab(initialTab)
} else {
queryTab = JSON.parse(queryTab)
if (tab !== queryTab) setTab(queryTab)
}
setDidMount(true)
}, [])

useEffect(() => {
if (tab !== undefined && didMount) pushToUrl(tab)
}, [tab])

return [
tab,
(e, { activeIndex }) => {
setTab(activeIndex)
}
]
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import React, { Component } from 'react'
import React, { useState } from 'react'
import { Tab, Grid, Radio, Menu } from 'semantic-ui-react'
import { withRouter } from 'react-router-dom'
import { shape } from 'prop-types'
import { dataSeriesType, viewModeNames } from './Panes/util'
import PassRate from './Panes/passRate'
import Distribution from './Panes/distribution'
import Tables from './Panes/tables'
import { useTabs } from '../../../common'

import './resultTabs.css'

Expand All @@ -13,84 +16,29 @@ const paneViewIndex = {
GRADE_DISTRIBUTION: 2
}

class ResultTabs extends Component {
state = {
activeIndex: paneViewIndex.TABLE,
viewMode: viewModeNames.CUMULATIVE,
isRelative: false
}

getPanes = () => {
const { primary, comparison } = this.props
const { viewMode, isRelative } = this.state

const paneMenuItems = [
{
menuItem: { key: 'Table', icon: 'table', content: 'Table' },
renderFn: () =>
(<Tables
comparison={comparison}
primary={primary}
viewMode={viewMode}
/>)
},
{
menuItem: { key: 'pass', icon: 'balance', content: 'Pass rate chart' },
renderFn: () =>
(<PassRate
comparison={comparison}
primary={primary}
viewMode={viewMode}
isRelative={isRelative && comparison}
/>)
},
{
menuItem: { key: 'grade', icon: 'chart bar', content: 'Grade distribution chart' },
renderFn: () =>
(<Distribution
comparison={comparison}
primary={primary}
viewMode={viewMode}
isRelative={isRelative && comparison}
/>)
}
]

return paneMenuItems.map((p) => {
const { menuItem, renderFn } = p
return {
menuItem,
render: () => (
<Grid padded="vertically" columns="equal">
<Grid.Row className="modeSelectorRow">
{this.renderViewModeSelector()}
</Grid.Row>
{renderFn()}
</Grid>
)
}
})
}

handleTabChange = (e, { activeIndex }) => {
const { viewMode, activeIndex: oldIndex } = this.state
const resetViewMode = oldIndex === paneViewIndex.TABLE
const ResultTabs = (props) => {
const [tab, setTab] = useTabs(
'cs_tab',
0,
props.history
)
const [viewMode, setViewMode] = useState(viewModeNames.CUMULATIVE)
const [isRelative, setIsRelative] = useState(false)

const handleTabChange = (...params) => {
const resetViewMode = params[1].activeIndex === paneViewIndex.TABLE
&& viewMode === viewModeNames.GRADES

this.setState({
activeIndex,
viewMode: resetViewMode ? viewModeNames.CUMULATIVE : viewMode
})
setTab(...params)
setViewMode(resetViewMode ? viewModeNames.CUMULATIVE : viewMode)
}

handleModeChange = (viewMode) => {
this.setState({ viewMode })
const handleModeChange = (newViewMode) => {
setViewMode(newViewMode)
}

renderViewModeSelector = () => {
const { activeIndex, viewMode } = this.state

const isTogglePane = activeIndex !== 0
const renderViewModeSelector = () => {
const isTogglePane = tab !== 0

const getButtonMenu = () => (
<Menu secondary>
Expand All @@ -99,7 +47,7 @@ class ResultTabs extends Component {
key={name}
name={name}
active={viewMode === name}
onClick={() => this.handleModeChange(name)}
onClick={() => handleModeChange(name)}
/>))}
</Menu>
)
Expand All @@ -116,17 +64,17 @@ class ResultTabs extends Component {
id={toggleId}
checked={isToggleChecked}
toggle
onChange={() => this.handleModeChange(newMode)}
onChange={() => handleModeChange(newMode)}
/>
<label className="toggleLabel" htmlFor={toggleId}>{viewModeNames.STUDENT}</label>
</div>
{this.props.comparison &&
{props.comparison &&
<div className="toggleContainer">
<label className="toggleLabel">Absolute</label>
<Radio
toggle
checked={this.state.isRelative}
onChange={() => this.setState({ isRelative: !this.state.isRelative })}
checked={isRelative}
onChange={() => setIsRelative(!isRelative)}
/>
<label className="toggleLabel">Relative</label>
</div>
Expand All @@ -142,24 +90,76 @@ class ResultTabs extends Component {
)
}

render() {
return (
<div>
<Tab
panes={this.getPanes()}
onTabChange={this.handleTabChange}
/>
</div>)
const getPanes = () => {
const { primary, comparison } = props

const paneMenuItems = [
{
menuItem: { key: 'Table', icon: 'table', content: 'Table' },
renderFn: () =>
(<Tables
comparison={comparison}
primary={primary}
viewMode={viewMode}
/>)
},
{
menuItem: { key: 'pass', icon: 'balance', content: 'Pass rate chart' },
renderFn: () =>
(<PassRate
comparison={comparison}
primary={primary}
viewMode={viewMode}
isRelative={isRelative && comparison}
/>)
},
{
menuItem: { key: 'grade', icon: 'chart bar', content: 'Grade distribution chart' },
renderFn: () =>
(<Distribution
comparison={comparison}
primary={primary}
viewMode={viewMode}
isRelative={isRelative && comparison}
/>)
}
]

return paneMenuItems.map((p) => {
const { menuItem, renderFn } = p
return {
menuItem,
render: () => (
<Grid padded="vertically" columns="equal">
<Grid.Row className="modeSelectorRow">
{renderViewModeSelector()}
</Grid.Row>
{renderFn()}
</Grid>
)
}
})
}

return (
<div>
<Tab
panes={getPanes()}
onTabChange={handleTabChange}
activeIndex={tab}
/>
</div>
)
}

ResultTabs.propTypes = {
primary: dataSeriesType.isRequired,
comparison: dataSeriesType
comparison: dataSeriesType,
history: shape({}).isRequired
}

ResultTabs.defaultProps = {
comparison: undefined
}

export default ResultTabs
export default withRouter(ResultTabs)
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ class PopulationCourseStats extends Component {
reversed={reversed}
/>
<Table.HeaderCell content={0} />
{courseGradesTypes.map(g => <Table.HeaderCell content={g} />)}
{courseGradesTypes.map(g => <Table.HeaderCell content={g} key={g} />)}
<Table.HeaderCell content="Other passed" />
</Table.Row>
</Table.Header>
Expand Down
Loading

0 comments on commit 8e6491b

Please sign in to comment.