renderTriggerAssignment () { const { student, triggerAssignment } = this.props const { assignment, submission } = triggerAssignment || {} const submissionUrl = `/courses/${assignment.course_id}/assignments/${assignment.id}/submissions/${student.id}` let submissionDate = null if (submission) { submissionDate = submission.submitted_at ? I18n.l('date.formats.long', new Date(submission.submitted_at)) : null } else { submissionDate = I18n.t('Not Submitted') } return ( <section className="crs-student-details__score-content"> <h3 className="crs-student-details__score-number">{i18nGrade(submission.grade, assignment)}</h3> <div className="crs-student-details__score-title">{assignment.name}</div> { submissionDate ? ( <div className="crs-student-details__score-date">{I18n.t('Submitted: %{submitDate}', { submitDate: submissionDate })}</div> ) : null } <a target="_blank" rel="noopener noreferrer" href={submissionUrl} className="crs-breakdown__link"> {I18n.t('View Submission')} </a> </section> ) }
renderStudentProfile () { const { student, triggerAssignment } = this.props const { assignment } = triggerAssignment const studentAvatar = student.avatar_image_url || '/images/messages/avatar-50.png' const conversationUrl = `/conversations?context_id=course_${assignment.course_id}&user_id=${student.id}&user_name=${student.name}` return ( <section className="crs-student-details__profile-content"> <button className="Button Button--icon-action student-details__prev-student" aria-label={I18n.t('view previous student')} onClick={this.props.selectPrevStudent} type="button" > <i aria-hidden className="icon-arrow-open-left" /> </button> <div className="crs-student-details__profile-inner-content"> <img src={studentAvatar} aria-hidden className="crs-student-details__profile-image" /> <h3 className="crs-student-details__name">{student.name}</h3> <a target="_blank" rel="noopener noreferrer" href={conversationUrl} className="crs-breakdown__link"> <i aria-hidden className="icon-email crs-icon-email" />{I18n.t('Send Message')} </a> </div> <button className="Button Button--icon-action student-details__next-student" aria-label={I18n.t('view next student')} onClick={this.props.selectNextStudent} type="button" > <i aria-hidden className="icon-arrow-open-right" /> </button> </section> ) }
renderContent () { if (this.props.isLoading) { return ( <div className='crs-breakdown-graph__loading'> <Spinner title={I18n.t('Loading')} size='small' /> <p>{I18n.t('Loading Data..')}</p> </div> ) } else { return this.renderBars() } }
render () { const avatar = this.props.student.user.avatar_image_url || '/images/messages/avatar-50.png' // default const { trend } = this.props.student const trendClasses = classNames({ 'crs-student__trend-icon': true, 'crs-student__trend-icon__positive': trend === 1, 'crs-student__trend-icon__neutral': trend === 0, 'crs-student__trend-icon__negative': trend === -1, }) const showTrend = trend !== null && trend !== undefined return ( <div className='crs-student-range__item'> <img src={avatar} className='crs-student__avatar' onClick={this.selectStudent}/> <button className='crs-student__name crs-link-button' onClick={this.selectStudent} aria-label={I18n.t('Select student %{name}', { name: this.props.student.user.name })} > {this.props.student.user.name} </button> {showTrend && (<span className={trendClasses}></span>)} </div> ) }
render () { return ( <div className='crs-breakdown-graph' > <h2>{I18n.t('Mastery Paths Breakdown')}</h2> {this.renderContent()} </div> ) }
renderContent () { if (this.props.isLoading) { return ( <div className="crs-student-details__loading"> <Spinner title={I18n.t('Loading')} size="small" /> <p>{I18n.t('Loading Data..')}</p> </div> ) } else if (this.props.student) { return ( <div> {this.renderStudentProfile()} {this.renderTriggerAssignment()} {this.renderFollowOnAssignments()} </div> ) } return null }
render () { return ( <div className='crs-ranges-view'> <header className='crs-ranges-view__header'> <h4>{I18n.t('Mastery Paths Breakdown')}</h4> </header> <ApplyTheme theme={tabsTheme}> <TabList variant='accordion' selectedIndex={this.props.selectedPath.range} onChange={this.props.selectRange}> {this.renderTabs()} </TabList> </ApplyTheme> </div> ) }
renderHeader () { if (!this.props.student) { return null } return ( <header className="crs-student-details__header"> <button className="crs-breakdown__link crs-back-button" ref={(e) => { this.backButton = e }} onClick={this.props.unselectStudent} > <i aria-hidden className="icon-arrow-open-left" /> {I18n.t('Back')} </button> </header> ) }
render () { const { selectedPath, ranges, students } = this.props const selectedStudent = selectedPath.student !== null ? ranges[selectedPath.range].students[selectedPath.student].user : null const studentDetails = selectedPath.student !== null && selectedStudent ? students[selectedStudent.id] : null return ( <Tray open={this.props.showDetails} placement="end" shouldContainFocus defaultFocusElement={() => this.closeButton} applicationElement={() => document.getElementById('application')} > <div className="crs-breakdown-details"> <div className="crs-breakdown-details__content"> <span className="crs-breakdown-details__closeButton"> <Button variant="icon" ref={(e) => { this.closeButton = e }} onClick={this.props.closeSidebar} > <span className="crs-breakdown-details__closeButtonIcon"> <IconX title={I18n.t('Close details sidebar')} /> </span> </Button> </span> <StudentRangeView assignment={this.props.assignment} ranges={ranges} selectedPath={selectedPath} selectRange={this.props.selectRange} selectStudent={this.props.selectStudent} student={selectedStudent} /> <StudentDetailsView isLoading={this.props.isStudentDetailsLoading} student={selectedStudent} triggerAssignment={studentDetails && studentDetails.triggerAssignment} followOnAssignments={studentDetails && studentDetails.followOnAssignments} selectPrevStudent={this.selectPrevStudent} selectNextStudent={this.selectNextStudent} unselectStudent={this.unselectStudent} /> </div> </div> </Tray> ); }
render () { const isHidden = !!this.props.student const classes = classNames({ 'crs-ranges-view': true, 'crs-ranges-view__hidden': isHidden, }) return ( <div className={classes}> <header className='crs-ranges-view__header'> <h4>{I18n.t('Mastery Paths Breakdown')}</h4> </header> {this.renderTabs()} </div> ) }