UNPKG

@instructure/quiz-taking

Version:
173 lines (151 loc) • 5.54 kB
import React, {Component} from 'react' import PropTypes from 'prop-types' import ImmutablePropTypes from 'react-immutable-proptypes' import extractTextFromHtml from '@instructure/quiz-interactions/util/extractTextFromHtml' import {substituteVars} from '@instructure/quiz-interactions/components/formula/common/util' import t from '@instructure/quiz-i18n/format-message' import {generateDisplayPositions} from '@instructure/quiz-core/common/util/generateDisplayPositions' import {Stimulus} from '@instructure/quiz-core/common/components/layout/sidebar/Stimulus/index' import {Sidebar} from '@instructure/quiz-core/common/components/layout/sidebar/Sidebar/index' import {onPhone} from '@instructure/quiz-core/common/util/windowChecks' import SidebarItem from './SidebarItem' import {SIDEBAR_ITEM_REF, FORMULA_SLUG} from '@instructure/quiz-common/constants' import {withI18nSupport} from '@instructure/quiz-common/with-i18n-support' export class TakingSidebar extends withI18nSupport(Component) { static propTypes = { allowBacktracking: PropTypes.bool.isRequired, quizTitle: PropTypes.string.isRequired, setFocusTitleAndInstructions: PropTypes.func.isRequired, goToItem: PropTypes.func.isRequired, isOneQuestionAtATime: PropTypes.bool.isRequired, pinnedItems: ImmutablePropTypes.listOf( PropTypes.shape({ sessionItemId: PropTypes.string.isRequired, position: PropTypes.number.isRequired, }), ).isRequired, role: PropTypes.string, screenreaderNotification: PropTypes.func.isRequired, scrollToItem: PropTypes.func.isRequired, sessionItems: ImmutablePropTypes.list.isRequired, sessionNotLoaded: PropTypes.bool.isRequired, sidebarOpen: PropTypes.bool, toggleSidebar: PropTypes.func.isRequired, locale: PropTypes.string, } static defaultProps = { role: 'navigation', sidebarOpen: false, locale: null, } static contextTypes = { locale: PropTypes.string, } generateItemKey(id) { return `${SIDEBAR_ITEM_REF}_${id}` } setRef(key) { return node => { this[key] = node } } scrollToItem = position => itemId => { if (this.props.isOneQuestionAtATime) this.scrollToItemOqaat(position, itemId) else this.props.scrollToItem(itemId) if (onPhone() && this.props.sidebarOpen) this.props.toggleSidebar() } scrollToItemOqaat = (position, itemId) => { const itemMessage = t('Current question changed to question {position, number}', { position: position || 1, }) const message = position ? itemMessage : `${t('Navigated to quiz title and instructions.')} ${itemMessage}` this.props.setFocusTitleAndInstructions(!position) this.props.goToItem(position || 1) if (!position) { setTimeout(() => { this.props.scrollToItem(itemId) this.props.screenreaderNotification(message) }, 100) } else { this.props.screenreaderNotification(message) } } getItemBody(item, locale) { let itemBody = item.getItemBody() if (item.getInteractionType().slug === FORMULA_SLUG) { const variables = item.toJS().interactionData.variables itemBody = substituteVars(itemBody, variables, locale) } return extractTextFromHtml(itemBody || '') } renderSidebarItem = (sessionItem, _displayPosition) => { const item = sessionItem.getItem() const key = this.generateItemKey(item.id) const {sidebarOpen} = this.props return ( <SidebarItem inStimulus={sessionItem.isStimulus} itemBody={this.getItemBody(item, this.locale)} itemId={item.id} itemName={item.getInteractionType().name} key={key} pointsPossible={sessionItem.pointsPossible} position={sessionItem.questionNumber} actualPosition={sessionItem.position} quizEntryId={sessionItem.id} ref={this.generateItemKey(item.id)} scrollToItem={this.scrollToItem(sessionItem.bolaPosition || sessionItem.position)} sessionItem={sessionItem} sidebarOpen={sidebarOpen} /> ) } renderSidebarItems() { const {sessionItems} = this.props return generateDisplayPositions(sessionItems).map(si => { const sessionItem = si.record const {sidebarOpen} = this.props if (sessionItem.isStimulus) { const key = this.generateItemKey(si.record.id) return ( <Stimulus displayPosition={si.displayPosition} itemId={sessionItem.id} key={key} ref={this.setRef(key)} renderSidebarItem={this.renderSidebarItem} scrollToItem={this.scrollToItem(sessionItem.bolaPosition || sessionItem.position)} sidebarOpen={sidebarOpen} stimulusParent={sessionItem} /> ) } return <div key={sessionItem.id}>{this.renderSidebarItem(sessionItem)}</div> }) } render() { if ( this.props.sessionNotLoaded || (this.props.isOneQuestionAtATime && !this.props.allowBacktracking) ) { return null } return ( <Sidebar taking role={this.props.role} title={this.props.quizTitle} pinnedItems={this.props.pinnedItems} scrollToItem={this.scrollToItem} sidebarOpen={this.props.sidebarOpen} toggleSidebar={this.props.toggleSidebar} screenreaderNotification={this.props.screenreaderNotification} > {this.renderSidebarItems()} </Sidebar> ) } } export default TakingSidebar