UNPKG

@instructure/quiz-interactions

Version:

A React UI component Library for quiz interaction types.

207 lines (169 loc) • 5.76 kB
import React, {createContext, useContext} from 'react' import update from 'immutability-helper' import findIndex from 'lodash/findIndex' import omit from 'lodash/omit' import without from 'lodash/without' const CategorizationPresenterContext = createContext(null) function CategorizationPresenterProvider({ interactionData, scoringData, changeItemState, newId, children, }) { // ============= // HELPERS // ============= function getCategoryOrder() { // This is to protect against quizzes which were // created before categoryOrder was introduced return interactionData.categoryOrder || Object.keys(interactionData.categories) } function updateInteractionData(updates) { changeItemState({ interactionData: Object.assign({}, interactionData || {}, updates), }) } // =========== // ACTIONS - CATEGORIES // =========== function onCategoryInputChange(itemId, e) { const categories = update(interactionData.categories, { [itemId]: {itemBody: {$set: e.target.value}}, }) updateInteractionData({categories}) } function onCreateCategory() { const newItemId = newId() const newItem = {id: newItemId, itemBody: ''} const newCategories = update(interactionData.categories, { [newItemId]: {$set: newItem}, }) const newCategoryOrder = update(getCategoryOrder(), { $push: [newItemId], }) const newCategoryScoringData = { id: newItemId, scoringAlgorithm: 'AllOrNothing', scoringData: { value: [], }, } const newInteractionData = update(interactionData, { categories: {$set: newCategories}, categoryOrder: {$set: newCategoryOrder}, }) const newScoringData = update(scoringData, { value: { $push: [newCategoryScoringData], }, }) changeItemState({interactionData: newInteractionData, scoringData: newScoringData}) } function onRemoveCategory(categoryId) { const newCategories = omit(interactionData.categories, categoryId) const newCategoryOrder = getCategoryOrder().filter(c => c !== categoryId) const newDistractors = omit( interactionData.distractors, scoringData.value.filter(item => item.id === categoryId)[0].scoringData.value, ) const newScoringDataValue = scoringData.value.filter(item => item.id !== categoryId) const newInteractionData = update(interactionData, { categoryOrder: {$set: newCategoryOrder}, categories: {$set: newCategories}, distractors: {$set: newDistractors}, }) const newScoringData = update(scoringData, { value: { $set: newScoringDataValue, }, }) changeItemState({interactionData: newInteractionData, scoringData: newScoringData}) } // =========== // ACTIONS - ANSWERS // =========== function onCreateAnswer(categoryId) { const newItemId = newId() const newItem = {id: newItemId, itemBody: ''} const newDistractors = update(interactionData.distractors, { [newItemId]: {$set: newItem}, }) const scoringDataCategoryIndex = findIndex(scoringData.value, item => item.id === categoryId) const newInteractionData = update(interactionData, { distractors: {$set: newDistractors}, }) const newScoringData = update(scoringData, { value: { [scoringDataCategoryIndex]: { scoringData: { value: { // because kinesis does not save empty arrays well, // we need to guard against this being null $apply: answersList => (answersList || []).concat([newItemId]), }, }, }, }, }) changeItemState({interactionData: newInteractionData, scoringData: newScoringData}) } function onRemoveAnswer(itemId, categoryId) { const newDistractors = omit(interactionData.distractors, itemId) const scoringDataCategoryIndex = findIndex(scoringData.value, item => item.id === categoryId) const scoringDataCategory = scoringData.value[scoringDataCategoryIndex] const newCategScoringDataValues = without(scoringDataCategory.scoringData.value, itemId) const newInteractionData = update(interactionData, { distractors: {$set: newDistractors}, }) const newScoringData = update(scoringData, { value: { [scoringDataCategoryIndex]: { scoringData: { value: {$set: newCategScoringDataValues}, }, }, }, }) changeItemState({interactionData: newInteractionData, scoringData: newScoringData}) } // =========== // ACTIONS - DISTRACTORS // =========== function onDistractorInputChange(itemId, e) { const distractors = update(interactionData.distractors, { [itemId]: {itemBody: {$set: e.target.value}}, }) updateInteractionData({distractors}) } function onRemoveDistractor(itemId) { const newList = omit(interactionData.distractors, itemId) const newInteractionData = update(interactionData, { distractors: {$set: newList}, }) changeItemState({ interactionData: newInteractionData, }) } const value = { getCategoryOrder, updateInteractionData, onCategoryInputChange, onCreateCategory, onRemoveCategory, onCreateAnswer, onRemoveAnswer, onDistractorInputChange, onRemoveDistractor, } return ( <CategorizationPresenterContext.Provider value={value}> {children} </CategorizationPresenterContext.Provider> ) } function useCategorizationPresenter() { return useContext(CategorizationPresenterContext) } export {CategorizationPresenterContext, CategorizationPresenterProvider, useCategorizationPresenter} export default CategorizationPresenterProvider