Skip to content
Snippets Groups Projects
FeedbackPanel.jsx 4.48 KiB
Newer Older
import React from 'react'
import Notification from 'react-bulma-notification'

Thomas Roos's avatar
Thomas Roos committed
import * as api from '../../api.jsx'

import withShortcuts from '../ShortcutBinder.jsx'
import FeedbackBlock from './FeedbackBlock.jsx'
Thomas Roos's avatar
Thomas Roos committed

class FeedbackPanel extends React.Component {
  feedbackBlock = React.createRef();

    submissionID: null,
    selectedFeedbackIndex: null
  }

  componentDidMount = () => {
    if (this.props.grading) {
      this.props.bindShortcut(['up', 'k'], (event) => {
        event.preventDefault()
        this.prevOption()
      })
      this.props.bindShortcut(['down', 'j'], (event) => {
        event.preventDefault()
        this.nextOption()
      })
      this.props.bindShortcut(['space'], (event) => {
        event.preventDefault()
        this.toggleSelectedOption()
      })
    }
Thomas Roos's avatar
Thomas Roos committed

  static getDerivedStateFromProps (nextProps, prevState) {
    if (prevState.problemID !== nextProps.problem.id || prevState.submissionID !== nextProps.submissionID) {
      return {
        remark: nextProps.grading && nextProps.solution.remark,
        submissionID: nextProps.submissionID,
        selectedFeedbackIndex: null
Thomas Roos's avatar
Thomas Roos committed

  setOptionIndex = (newIndex) => {
    if (this.props.problem.feedback.length === 0) return
    let length = this.props.problem.feedback.length
    newIndex = ((newIndex % length) + length) % length
    this.setState({
      selectedFeedbackIndex: newIndex
    })
  }

  prevOption = () => {
    let index = this.state.selectedFeedbackIndex !== null ? this.state.selectedFeedbackIndex : 0
    this.setOptionIndex(index - 1)
  }

  nextOption = () => {
    let index = this.state.selectedFeedbackIndex !== null ? this.state.selectedFeedbackIndex : -1
    this.setOptionIndex(index + 1)
  }

  toggleSelectedOption = () => {
    if (this.feedbackBlock.current) {
      this.feedbackBlock.current.toggle()
    }
  }

    if (!this.props.solution.graded_at && this.state.remark.replace(/\s/g, '').length === 0) return
    api.post('solution/' + this.props.examID + '/' + this.props.submissionID + '/' + this.props.problem.id, {
      remark: this.state.remark,
      graderID: this.props.graderID
    })
Anton Akhmerov's avatar
Anton Akhmerov committed
      .then(success => {
        this.props.updateSubmission()
Anton Akhmerov's avatar
Anton Akhmerov committed
        if (!success) Notification.error('Remark not saved!')
Thomas Roos's avatar
Thomas Roos committed

  changeRemark = (event) => {
    this.setState({
      remark: event.target.value
    })
  }
    const blockURI = this.props.examID + '/' + this.props.submissionID + '/' + this.props.problem.id

    let totalScore = 0
    if (this.props.grading) {
      for (let i = 0; i < this.props.solution.feedback.length; i++) {
        const probIndex = this.props.problem.feedback.findIndex(fb => fb.id === this.props.solution.feedback[i])
        if (probIndex >= 0) totalScore += this.props.problem.feedback[probIndex].score
      }
    let selectedFeedbackId = this.state.selectedFeedbackIndex !== null &&
      this.props.problem.feedback[this.state.selectedFeedbackIndex].id

      <React.Fragment>
        {this.props.grading &&
          <p className='panel-heading'>
            Total:&nbsp;<b>{totalScore}</b>
          </p>}
        {this.props.problem.feedback.map((feedback, index) =>
          <FeedbackBlock key={feedback.id} uri={blockURI} graderID={this.props.graderID}
            feedback={feedback} checked={this.props.grading && this.props.solution.feedback.includes(feedback.id)}
            editFeedback={() => this.props.editFeedback(feedback)} updateSubmission={this.props.updateSubmission}
            ref={(selectedFeedbackId === feedback.id) ? this.feedbackBlock : null} grading={this.props.grading}
            selected={selectedFeedbackId === feedback.id || feedback.highlight} showIndex={this.props.showTooltips} index={index + 1} />
        {this.props.grading &&
          <div className='panel-block'>
            <textarea className='textarea' rows='2' placeholder='remark' value={this.state.remark} onBlur={this.saveRemark} onChange={this.changeRemark} />
          </div>
        }
          <button className='button is-link is-outlined is-fullwidth' onClick={() => this.props.editFeedback()}>
            <span className='icon is-small'>
              <i className='fa fa-plus' />
            </span>
            <span>option</span>
          </button>
        </div>
      </React.Fragment>
Thomas Roos's avatar
Thomas Roos committed
}
export default withShortcuts(FeedbackPanel)