@instructure/quiz-interactions
Version:
A React UI component Library for quiz interaction types.
137 lines (125 loc) • 4.12 kB
JavaScript
/** @jsx jsx */
import {Component} from 'react'
import PropTypes from 'prop-types'
import get from 'lodash/get'
import {Text} from '@instructure/ui-text'
import {jsx} from '@instructure/emotion'
import t from '@instructure/quiz-i18n/format-message'
import {ItemBodyWrapper} from '@instructure/quiz-rce/components/ItemBodyWrapper/index'
import {RichContentRenderer} from '@instructure/quiz-rce/components/RichContentRenderer/index'
import {SubjectiveFeedback} from '@instructure/quiz-results-feedback'
import {WordCount} from '../helpers/WordCount'
import generateStyle from './styles'
import generateComponentTheme from './theme'
import {withStyleOverrides} from '@instructure/quiz-common/util/withStyleOverrides'
/**
---
category: Essay
---
Essay Result component
```jsx_example
<SettingsSwitcher locales={LOCALES}>
<EssayResult
itemBody="Why did the Roman Empire fall?"
interactionData={{
rce: true,
spellCheck: true,
wordCount: true,
wordLimitEnabled: true,
wordLimitMax: 10,
wordLimitMin: 1
}}
scoredData={{ value: 'goths and food shortage', gradeStatus: 'waiting' }}
scoringData={{ value: 'these are the grading notes' }}
/>
</SettingsSwitcher>
```
**/
(generateStyle, generateComponentTheme)
export default class EssayResult extends Component {
static displayName = 'EssayResult'
static componentId = `Quizzes${this.displayName}`
static propTypes = {
interactionData: PropTypes.object.isRequired,
itemBody: PropTypes.string.isRequired,
scoredData: PropTypes.shape({
gradeStatus: PropTypes.oneOf(['waiting', 'graded', 'correct', 'incorrect']),
value: PropTypes.string,
}).isRequired,
scoringData: PropTypes.object,
styles: PropTypes.object,
}
static defaultProps = {
scoredData: {value: 'waiting'},
scoringData: void 0,
itemResultsModifications: void 0,
}
getGradeStatus() {
const workingGradeStatus = get(this.props, [
'itemResultsModifications',
'scoredData',
'gradeStatus',
])
return workingGradeStatus || this.props.scoredData.gradeStatus
}
renderGradingNotes() {
const gradingNotes = this.props.scoringData && this.props.scoringData.value
if (gradingNotes) {
return (
<div css={this.props.styles.gradingNotesWrapper}>
<Text color="primary" size="small" weight="bold">
{t('Grading Notes')}
</Text>
<div>
<Text color="primary" size="small">
{gradingNotes}
</Text>
</div>
</div>
)
}
}
renderEssay() {
const {value} = this.props.scoredData
const rceEnabled = this.props?.interactionData?.rce === true
let content
if (typeof value === 'undefined') {
content = t('(response not displayed)')
} else if (!value || (typeof value === 'object' && Object.keys(value).length === 0)) {
content = t('(no answer)')
} else {
content = value
}
if (this.props.interactionData.rce) {
return <RichContentRenderer customStyles={this.props.styles.userResponse} content={content} />
}
return (
<div
css={{...this.props.styles.userResponse, whiteSpace: !rceEnabled ? 'pre-wrap' : undefined}}
>
<Text color="primary" size="small">
{content}
</Text>
</div>
)
}
render() {
const gradeStatus = this.getGradeStatus()
const {interactionData} = this.props
return (
<ItemBodyWrapper itemBody={this.props.itemBody}>
<SubjectiveFeedback gradeStatus={gradeStatus}>{this.renderEssay()}</SubjectiveFeedback>
<WordCount
rce={interactionData.rce}
isEditing={false}
essay={this.props.scoredData.value}
wordCount={interactionData.wordCount}
wordLimitEnabled={interactionData.wordLimitEnabled}
wordLimitMin={interactionData.wordLimitMin}
wordLimitMax={interactionData.wordLimitMax}
/>
{this.renderGradingNotes()}
</ItemBodyWrapper>
)
}
}