@instructure/quiz-interactions
Version:
A React UI component Library for quiz interaction types.
153 lines (136 loc) • 4.11 kB
JavaScript
import React from 'react'
import times from 'lodash/times'
import {v4 as uuid} from 'uuid'
import {rule, each, onSelf} from 'instructure-validations'
import {Text} from '@instructure/ui-text'
import {CATEGORIZATION_SLUG} from '../../interaction_slugs'
import InteractionType from '../InteractionType'
import {presenceMessage, noDuplicatesMessage} from '../../util/validationHelpers'
import t from '@instructure/quiz-i18n/format-message'
export default class CategorizationInteractionType extends InteractionType {
constructor(obj) {
super()
super.initializeProps(obj)
}
slug = CATEGORIZATION_SLUG
translatedName = t('Categorization')
defaultProperties = {}
getDefaultScoringData = (intData, scoreMethod = 'all_or_nothing') => {
let i = 0
const categories = Object.keys(intData.categories).map(uuid => {
const matchingDistractorId = Object.keys(intData.distractors)[i]
i++
return {
id: uuid,
scoringAlgorithm: 'AllOrNothing',
scoringData: {
value: [matchingDistractorId],
},
}
})
return {
scoreMethod: scoreMethod,
value: categories,
}
}
getDefaultInteractionData = () => {
const [categoryIdA, categoryIdB, distractorIdA, distractorIdB] = times(4, uuid)
return {
categoryOrder: [categoryIdA, categoryIdB],
categories: {
[categoryIdA]: {id: categoryIdA, itemBody: ''},
[categoryIdB]: {id: categoryIdB, itemBody: ''},
},
distractors: {
[distractorIdA]: {id: distractorIdA, itemBody: ''},
[distractorIdB]: {id: distractorIdB, itemBody: ''},
},
}
}
getRenderedResponse = (responseValue, interactionData) => {
const distractors = interactionData.distractors
return (
<Text color="primary">
{responseValue
.map(category => {
const c = interactionData.categories[category.id]
const categoryValue = c ? c.itemBody : ''
const categoryDistractors = category.value
.map(distractorId => {
const distractorValue = distractors[distractorId]
return distractorValue ? distractorValue.itemBody : ''
})
.join(', ')
return t('Category: {categoryValue} | Distractors: {categoryDistractors}', {
categoryValue,
categoryDistractors,
})
})
.join(', ')}
</Text>
)
}
static useNewValidations = true
static validations = data => {
const scoringDataValue = data.scoringData.value
const categoryAnswers = scoringDataValue.reduce((list, v) => {
return list.concat(v.scoringData.value || [])
}, [])
return {
interactionData: {
categories: [
each({
itemBody: [
rule('presence', {
message: presenceMessage(t('Category')),
}),
],
}),
rule('noDuplicates', {
field: 'itemBody',
message: noDuplicatesMessage(t('Category')),
}),
],
distractors: [
each({
itemBody: [
rule('presence', {
message: presenceMessage(t('Distractor')),
}),
],
}),
rule('noDuplicates', {
field: 'itemBody',
message: noDuplicatesMessage(t('Distractor')),
}),
],
},
scoringData: {
value: [
onSelf(
rule('listSize', {
listOverride: categoryAnswers,
min: 1,
minMessage: t('You must have at least one answer in a category'),
}),
),
],
},
}
}
getDefaultUserResponse(intData) {
const categories = Object.keys(intData.categories).map(uuid => {
return {
id: uuid,
value: [],
type: 'ArrayText',
}
})
return {value: categories}
}
hasResponse(resp) {
return resp.some(category => {
return category.value.length > 0
})
}
}