Skip to content

Commit

Permalink
Evaluation improvements part 1(#219)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexscheitlin authored and rschlaefli committed Nov 20, 2017
1 parent b7b53b1 commit bcf2ee8
Show file tree
Hide file tree
Showing 13 changed files with 493 additions and 196 deletions.
412 changes: 281 additions & 131 deletions src/components/__snapshots__/storyshots.test.js.snap

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/components/evaluation/Chart.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ function Chart({
isSolutionShown={showSolution}
restrictions={restrictions}
statistics={statistics}
totalResponses={results.totalResponses}
/>
)
}
Expand Down
64 changes: 64 additions & 0 deletions src/components/evaluation/EvaluationListItem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import React from 'react'
import PropTypes from 'prop-types'

import { Icon } from 'semantic-ui-react'

const propTypes = {
children: PropTypes.element.isRequired,
color: PropTypes.string,
marker: PropTypes.string,
}

const defaultProps = {
color: undefined,
marker: undefined,
}

const EvaluationListItem = ({ color, children, marker }) => (
<div className="evaluationListItem">
{color && (
<div className="colorSquare">
<Icon name="square icon" />
</div>
)}
<div className="content">{children}</div>
{marker && <div className="marker">{marker}</div>}

<style jsx>{`
.evaluationListItem {
display: flex;
flex-flow: row wrap;
align-items: center;
padding: 0.1rem 0;
border-bottom: 1px solid lightgrey;
&:first-child {
border-top: 1px solid lightgrey;
}
.colorSquare :global(i) {
flex: 0 0 auto;
color: ${color};
}
.marker {
flex: 0 0 auto;
font-weight: bold;
}
.content {
flex: 1;
}
}
`}</style>
</div>
)

EvaluationListItem.propTypes = propTypes
EvaluationListItem.defaultProps = defaultProps

export default EvaluationListItem
35 changes: 15 additions & 20 deletions src/components/evaluation/Possibilities.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from 'react'
import PropTypes from 'prop-types'
import { List } from 'semantic-ui-react'
import { FormattedMessage } from 'react-intl'

import { QuestionTypes } from '../../constants'
import { CHART_COLORS, QuestionTypes } from '../../constants'
import { EvaluationListItem } from '.'

const propTypes = {
questionOptions: PropTypes.object.isRequired,
Expand Down Expand Up @@ -39,37 +39,32 @@ const Possibilities = ({ questionOptions, questionType }) => (
{(() => {
if ([QuestionTypes.SC, QuestionTypes.MC].includes(questionType)) {
return (
<List celled ordered>
{questionOptions.choices.map(choice => (
<List.Item key={choice.id}>{choice.name}</List.Item>
<div>
{questionOptions.choices.map((choice, index) => (
<EvaluationListItem
color={CHART_COLORS[index % 5]}
marker={String.fromCharCode(65 + index)}
>
{choice.name}
</EvaluationListItem>
))}
</List>
</div>
)
}

if (questionType === QuestionTypes.FREE) {
const { restrictions } = questionOptions

return (
<List celled>
<div>
{(() => {
const comp = []
if (restrictions.min) {
comp.push(
<List.Item>
<List.Header>Minimum</List.Header>
{restrictions.min}
</List.Item>,
)
comp.push(<EvaluationListItem marker="MIN">{restrictions.min}</EvaluationListItem>)
}

if (restrictions.max) {
comp.push(
<List.Item>
<List.Header>Maximum</List.Header>
{restrictions.max}
</List.Item>,
)
comp.push(<EvaluationListItem marker="MAX">{restrictions.max}</EvaluationListItem>)
}

if (comp.length > 0) {
Expand All @@ -78,7 +73,7 @@ const Possibilities = ({ questionOptions, questionType }) => (

return <div>No restrictions.</div>
})()}
</List>
</div>
)
}

Expand Down
55 changes: 28 additions & 27 deletions src/components/evaluation/Statistics.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import React from 'react'
import PropTypes from 'prop-types'
import _round from 'lodash/round'
import { Icon, List } from 'semantic-ui-react'
import { FormattedMessage } from 'react-intl'

import { EvaluationListItem } from '.'

const propTypes = {
max: PropTypes.number.isRequired,
mean: PropTypes.number.isRequired,
median: PropTypes.number.isRequired,
min: PropTypes.number.isRequired,
max: PropTypes.number,
mean: PropTypes.number,
median: PropTypes.number,
min: PropTypes.number,
}

const defaultProps = {
max: undefined,
mean: undefined,
median: undefined,
min: undefined,
}

const Statistics = ({
Expand All @@ -19,28 +27,20 @@ const Statistics = ({
<FormattedMessage defaultMessage="Statistics" id="teacher.evaluation.statistics.title" />
</h2>

<List celled>
<List.Item>
<List.Header>Minimum</List.Header>
{_round(min, 2)}
</List.Item>
<List.Item>
<List.Header>Maximum</List.Header>
{_round(max, 2)}
</List.Item>
<List.Item>
<List.Header>
Mean <Icon color="blue" name="square" />
</List.Header>
{_round(mean, 2)}
</List.Item>
<List.Item>
<List.Header>
Median <Icon color="red" name="square" />
</List.Header>
{_round(median, 2)}
</List.Item>
</List>
<div>
<EvaluationListItem color="white" marker="MIN">
{min ? _round(min, 2) : '-'}
</EvaluationListItem>
<EvaluationListItem color="white" marker="MAX">
{max ? _round(max, 2) : '-'}
</EvaluationListItem>
<EvaluationListItem color="Blue" marker="MEAN">
{mean ? _round(mean, 2) : '-'}
</EvaluationListItem>
<EvaluationListItem color="red" marker="MEDIAN">
{median ? _round(median, 2) : '-'}
</EvaluationListItem>
</div>

<style jsx>{`
.statistics {
Expand All @@ -54,5 +54,6 @@ const Statistics = ({
)

Statistics.propTypes = propTypes
Statistics.defaultProps = defaultProps

export default Statistics
37 changes: 33 additions & 4 deletions src/components/evaluation/charts/PieChart.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import {
Cell,
Pie,
PieChart as PieChartComponent,
Legend,
ResponsiveContainer,
Tooltip,
LabelList,
} from 'recharts'
import { withProps } from 'recompose'
import _round from 'lodash/round'

import { CHART_COLORS } from '../../../constants'

Expand Down Expand Up @@ -37,12 +39,29 @@ const PieChart = ({ isSolutionShown, data }) => (
}}
>
<Tooltip />
<Legend />
<Pie label data={data} fill="#8884d8" nameKey="value" valueKey="count">
<Pie labelLine data={data} fill="#8884d8" innerRadius={5} nameKey="value" valueKey="count">
<LabelList
fill="black"
offset={30}
position="outside"
stroke="black"
strokeWidth={1}
style={{ fontSize: '1.5rem' }}
valueAccessor={entry => `${entry.count} | ${entry.percentage}`}
/>
<LabelList
dataKey="label"
fill="white"
position="inside"
stroke="white"
strokeWidth={1}
style={{ fontSize: '3rem' }}
/>
{data.map((row, index) => (
<Cell
fill={isSolutionShown && row.correct ? '#00FF00' : CHART_COLORS[index % 5]}
key={row.value}
strokeWidth={5}
/>
))}
</Pie>
Expand All @@ -53,4 +72,14 @@ const PieChart = ({ isSolutionShown, data }) => (
PieChart.propTypes = propTypes
PieChart.defaultProps = defaultProps

export default PieChart
export default withProps(({ data, totalResponses }) => ({
// filter out choices without any responses (weird labeling)
// map data to contain percentages and char labels
data: data.filter(({ count }) => count > 0).map(({ correct, count, value }, index) => ({
correct,
count,
label: String.fromCharCode(65 + index),
percentage: `${_round(100 * (count / totalResponses), 2)} %`,
value,
})),
}))(PieChart)
2 changes: 1 addition & 1 deletion src/components/evaluation/charts/TableChart.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@ function TableChart({ data, isSolutionShown }) {
sortProperties={[{ id: 'count', sortAscending: false }]}
>
<RowDefinition>
<ColumnDefinition id="value" title="Value" />
<ColumnDefinition
cssClassName="griddle-cell countColumn"
id="count"
title="Count"
width="3rem"
/>
<ColumnDefinition id="value" title="Value" />
<ColumnDefinition
cssClassName="griddle-cell solutionColumn"
customComponent={ColumnWithSolution}
Expand Down
11 changes: 11 additions & 0 deletions src/components/evaluation/evaluation.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
TableChart,
CloudChart,
Statistics,
EvaluationListItem,
} from '.'

import { intlMock } from '../../../.storybook/utils'
Expand All @@ -34,6 +35,16 @@ const dataFREE = [

storiesOf('evaluation/components', module)
.add('Chart', () => <Chart />)
.add('EvaluationListItem', () => (
<div>
<EvaluationListItem color="red" marker="MIN">
hello world
</EvaluationListItem>
<EvaluationListItem color="blue">hello world 2</EvaluationListItem>
<EvaluationListItem marker="MAX">hello world 3</EvaluationListItem>
<EvaluationListItem>hello world 4</EvaluationListItem>
</div>
))
.add('Info', () => <Info />)
.add('Possibilities (SC)', () => (
<Possibilities
Expand Down
1 change: 1 addition & 0 deletions src/components/evaluation/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ export { default as Info } from './Info'
export { default as Possibilities } from './Possibilities'
export { default as VisualizationType } from './VisualizationType'
export { default as Statistics } from './Statistics'
export { default as EvaluationListItem } from './EvaluationListItem'
4 changes: 4 additions & 0 deletions src/components/layouts/EvaluationLayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const propTypes = {
onToggleShowSolution: PropTypes.func.isRequired,
options: PropTypes.object.isRequired,
pageTitle: PropTypes.string,
showSolution: PropTypes.bool,
statistics: PropTypes.shape({
mean: PropTypes.number.isRequired,
median: PropTypes.number.isRequired,
Expand All @@ -39,13 +40,15 @@ const defaultProps = {
description: undefined,
instanceSummary: [],
pageTitle: 'EvaluationLayout',
showSolution: false,
statistics: undefined,
totalResponses: undefined,
}

function EvaluationLayout({
intl,
pageTitle,
showSolution,
onToggleShowSolution,
chart,
type,
Expand Down Expand Up @@ -91,6 +94,7 @@ function EvaluationLayout({
<div className="settings">
<Checkbox
toggle
defaultChecked={showSolution}
label={intl.formatMessage({
defaultMessage: 'Show solution',
id: 'teacher.evaluation.showSolution.label',
Expand Down
32 changes: 31 additions & 1 deletion src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,34 @@ export const FREERestrictionTypes = {
RANGE: 'RANGE',
}

export const CHART_COLORS = ['#7CB8E4', '#976F34', '#E4BA7C', '#A4D9FF', '#437497']
// \cite{https://www.viget.com/articles/add-colors-to-your-palette-with-color-mixing}
// original circle
/* export const CHART_COLORS = [
rgb(19, 149, 186), // 1
rgb(17, 120, 153), // 2
rgb(15, 91, 120), // 3
rgb(13, 60, 85), // 4
rgb(192, 46, 29), // 5
rgb(217, 78, 31), // 6
rgb(241, 108, 32), // 7
rgb(239, 139, 44), // 8
rgb(236, 170, 56), // 9
rgb(235, 200, 68), // 10
rgb(162, 184, 108),// 11
rgb(92, 167, 147),// 12
] */

export const CHART_COLORS = [
'rgb(19, 149, 186)', // 1
'rgb(241, 108, 32)', // 7
'rgb(13, 60, 85)', // 4
'rgb(235, 200, 68)', // 10
'rgb(192, 46, 29)', // 5
'rgb(162, 184, 108)', // 11
'rgb(239, 139, 44)', // 8
'rgb(17, 120, 153)', // 2
'rgb(217, 78, 31)', // 6
'rgb(92, 167, 147)', // 12
'rgb(15, 91, 120)', // 3
'rgb(236, 170, 56)', // 9
]
Loading

0 comments on commit bcf2ee8

Please sign in to comment.