<commit_before>import React from 'react';
import apiClient from 'panoptes-client/lib/api-client';
import { VisibilitySplit } from 'seven-ten';
import SubjectViewer from '../components/subject-viewer';
import ClassificationSummary from './classification-summary';
import preloadSubject from '../lib/preload-subject';
import workflowAllowsFlipbook from '../lib/workflow-allows-flipbook';
import workflowAllowsSeparateFrames from '../lib/workflow-allows-separate-frames';
import FrameAnnotator from './frame-annotator';
import CacheClassification from '../components/cache-classification';
import Task from './task';
import RestartButton from './restart-button';
import MiniCourse from '../components/mini-course';
import Tutorial from '../components/tutorial';
import interventionMonitor from '../lib/intervention-monitor';
import experimentsClient from '../lib/experiments-client';
import TaskNav from './task-nav';
import ExpertOptions from './expert-options';

// For easy debugging
window.cachedClassification = CacheClassification;

export default class Classifier extends React.Component {
  constructor(props) {
    super(props);
    this.handleAnnotationChange = this.handleAnnotationChange.bind(this);
    this.handleSubjectImageLoad = this.handleSubjectImageLoad.bind(this);
    this.completeClassification = this.completeClassification.bind(this);
    this.toggleExpertClassification = this.toggleExpertClassification.bind(this);
    this.state = {
      expertClassification: null,
      selectedExpertAnnotation: -1,
      showingExpertClassification: false,
      subjectLoading: false,
      annotations: []
    };
  }

  componentWillMount() {
    this.props.classification.listen('change', () => {
      const { annotations } = this.props.classification;
      this.setState({ annotations });
    });
  }

  componentDidMount() {
    this.loadSubject(this.props.subject);
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.user !== this.props.user) {
      if (this.props.demoMode) {
        this.props.onChangeDemoMode(false);
      }
      if (this.props.classification.gold_standard) {
        this.props.classification.update({ gold_standard: undefined });
      }
    }

    if (nextProps.subject !== this.props.subject) {
      this.loadSubject(nextProps.subject);
    }

    if (this.props.subject !== nextProps.subject || (!this.context.geordi && !this.context.geordi.keys.subjectID)) {
      this.context.geordi.remember({ subjectID: nextProps.subject.id });
    }

    if (nextProps.classification !== this.props.classification) {
      this.props.classification.stopListening('change', () => {
        const { annotations } = this.props.classification;
        this.setState({ annotations });
      });

      nextProps.classification.listen('change', () => {
        const { annotations } = nextProps.classification;
        this.setState({ annotations });
      });
    }
  }

  componentWillUnmount() {
    this.props.classification.stopListening('change', () => {
      const { annotations } = this.props.classification;
      this.setState({ annotations });
    });
    try {
      !!this.context.geordi && this.context.geordi.forget(['subjectID']);
    } catch (err) {
      console.error(err);
    }
  }

  getExpertClassification(workflow, subject) {
    const awaitExpertClassification = Promise.resolve(
      apiClient.get('/classifications/gold_standard', {
        workflow_id: workflow.id,
        subject_ids: [subject.id]
      })
      .catch(() => [])
      .then(([expertClassification]) => expertClassification)
    );

    awaitExpertClassification.then((expertClassification) => {
      expertClassification = expertClassification || subject.expert_classification_data[workflow.id];
      if (this.props.workflow === workflow && this.props.subject === subject) {
        window.expertClassification = expertClassification;
        this.setState({ expertClassification });
      }
    });
  }

  loadClassificationsCount(subject) {
    let query = {};
    if (this.props.splits && this.props.splits['subject.first-to-classify']) {
      query = {<commit_msg>Reset state.annotations when a new classification loads. (#3698)<commit_after>import React from 'react';
import apiClient from 'panoptes-client/lib/api-client';
import { VisibilitySplit } from 'seven-ten';
import SubjectViewer from '../components/subject-viewer';
import ClassificationSummary from './classification-summary';
import preloadSubject from '../lib/preload-subject';
import workflowAllowsFlipbook from '../lib/workflow-allows-flipbook';
import workflowAllowsSeparateFrames from '../lib/workflow-allows-separate-frames';
import FrameAnnotator from './frame-annotator';
import CacheClassification from '../components/cache-classification';
import Task from './task';
import RestartButton from './restart-button';
import MiniCourse from '../components/mini-course';
import Tutorial from '../components/tutorial';
import interventionMonitor from '../lib/intervention-monitor';
import experimentsClient from '../lib/experiments-client';
import TaskNav from './task-nav';
import ExpertOptions from './expert-options';

// For easy debugging
window.cachedClassification = CacheClassification;

export default class Classifier extends React.Component {
  constructor(props) {
    super(props);
    this.handleAnnotationChange = this.handleAnnotationChange.bind(this);
    this.handleSubjectImageLoad = this.handleSubjectImageLoad.bind(this);
    this.completeClassification = this.completeClassification.bind(this);
    this.toggleExpertClassification = this.toggleExpertClassification.bind(this);
    this.updateAnnotations = this.updateAnnotations.bind(this);
    this.state = {
      expertClassification: null,
      selectedExpertAnnotation: -1,
      showingExpertClassification: false,
      subjectLoading: false,
      annotations: []
    };
  }

  componentWillMount() {
    this.props.classification.listen('change', this.updateAnnotations);
    this.updateAnnotations();
  }

  componentDidMount() {
    this.loadSubject(this.props.subject);
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.user !== this.props.user) {
      if (this.props.demoMode) {
        this.props.onChangeDemoMode(false);
      }
      if (this.props.classification.gold_standard) {
        this.props.classification.update({ gold_standard: undefined });
      }
    }

    if (nextProps.subject !== this.props.subject) {
      this.loadSubject(nextProps.subject);
    }

    if (this.props.subject !== nextProps.subject || (!this.context.geordi && !this.context.geordi.keys.subjectID)) {
      this.context.geordi.remember({ subjectID: nextProps.subject.id });
    }

    if (nextProps.classification !== this.props.classification) {
      const { annotations } = nextProps.classification;
      this.setState({ annotations });
    }
  }

  componentDidUpdate(prevProps) {
    if (prevProps.classification !== this.props.classification) {
      prevProps.classification.stopListening('change', this.updateAnnotations);
      this.props.classification.listen('change', this.updateAnnotations);
      this.updateAnnotations();
    }
  }

  componentWillUnmount() {
    this.props.classification.stopListening('change', this.updateAnnotations);
    try {
      !!this.context.geordi && this.context.geordi.forget(['subjectID']);
    } catch (err) {
      console.error(err);
    }
  }

  getExpertClassification(workflow, subject) {
    const awaitExpertClassification = Promise.resolve(
      apiClient.get('/classifications/gold_standard', {
        workflow_id: workflow.id,
        subject_ids: [subject.id]
      })
      .catch(() => [])
      .then(([expertClassification]) => expertClassification)
    );

    awaitExpertClassification.then((expertClassification) => {
      expertClassification = expertClassification || subject.expert_classification_data[workflow.id];
      if (this.props.workflow === workflow && this.props.subject === subject) {
        window.expertClassification = expertClassification;
        this.setState({ expertClassification });
      }
    });
  }

  updateAnnotations() {
    const { annotations } = this.props.classification;
    this.setState({ annotations });
  }

  loadClassificationsCount(subject) {
    let query = {};
    if (this.props.splits && this.props.splits['subject.first-to-classify']) {
      query = {
{'fraction_non_alphanumeric': 0.13075638272488666, 'fraction_numerical': 0.0007158196134574087, 'mean_word_length': 3.7684869169510806, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1756310', 'n_tokens_mistral': 2374, 'n_tokens_neox': 2280, 'n_words': 404}