<commit_before>import React from "react";
import { connect } from "react-redux";
import { fetchAndObserveData, trackEvent } from "../../actions/index";
import { getSortedStudents } from "../../selectors/dashboard-selectors";
import { Header } from "../../components/portal-dashboard/header";
import { ClassNav } from "../../components/portal-dashboard/class-nav";
import { LevelViewer } from "../../components/portal-dashboard/level-viewer";
import { StudentList } from "../../components/portal-dashboard/student-list";
import LoadingIcon from "../../components/report/loading-icon";
import DataFetchError from "../../components/report/data-fetch-error";
import { getSequenceTree } from "../../selectors/report-tree";
import { IResponse } from "../../api";
import { setStudentSort } from "../../actions/dashboard";

import css from "../../../css/portal-dashboard/portal-dashboard-app.less";
import { RootState } from "../../reducers";

interface IProps {
  isFetching: boolean;
  error: IResponse;
  clazzName: string;
  students: any;
  fetchAndObserveData: () => void;
  sequenceTree: any;
}

interface IState {
  initialLoading: boolean;
}

class PortalDashboardApp extends React.PureComponent<IProps, IState> {
  constructor(props: IProps) {
    super(props);
    this.state = {
      initialLoading: true
    };
  }

  componentDidMount() {
    const { fetchAndObserveData } = this.props;
    fetchAndObserveData();
  }

  componentDidUpdate(prevProps: IProps) {
    const { initialLoading } = this.state;
    const { isFetching } = this.props;
    if (initialLoading && !isFetching && prevProps.isFetching) {
      this.setState({ initialLoading: false });
    }
  }

  render() {
    const { clazzName, students, error, sequenceTree } = this.props;
    const { initialLoading } = this.state;
    // In order to list the activities in the correct order,
    // they must be obtained via the child reference in the sequenceTree …
    const activityTrees = sequenceTree && sequenceTree.get("children");
    return (
      <div className={css.portalDashboardApp}>
        <Header/>
        { activityTrees &&
          <div>
            <div className={css.navigation}>
              <ClassNav
                clazzName={clazzName}
                setStudentSort={setStudentSort}
                trackEvent={trackEvent}
              />
              <LevelViewer/>
            </div>
            <StudentList students={students}/>
          </div>
        }
        { error && <DataFetchError error={error} /> }
        { initialLoading && <LoadingIcon /> }
      </div>
    );
  }
}

function mapStateToProps(state: RootState) {
  const data = state.get("data");
  const error = data.get("error");
  const dataDownloaded = !error && !data.get("isFetching");
  return {
    isFetching: data.get("isFetching"),
    error,
    clazzName: dataDownloaded && state.getIn(["report", "clazzName"]),
    students: dataDownloaded && getSortedStudents(state),
    sequenceTree: dataDownloaded && getSequenceTree(state),
  };
}

const mapDispatchToProps = (dispatch: any, ownProps: any) => {<commit_msg>Add props to enable update to redux state when changing sort mode<commit_after>import React from "react";
import { connect } from "react-redux";
import { fetchAndObserveData, trackEvent } from "../../actions/index";
import { getSortedStudents } from "../../selectors/dashboard-selectors";
import { Header } from "../../components/portal-dashboard/header";
import { ClassNav } from "../../components/portal-dashboard/class-nav";
import { LevelViewer } from "../../components/portal-dashboard/level-viewer";
import { StudentList } from "../../components/portal-dashboard/student-list";
import LoadingIcon from "../../components/report/loading-icon";
import DataFetchError from "../../components/report/data-fetch-error";
import { getSequenceTree } from "../../selectors/report-tree";
import { IResponse } from "../../api";
import { setStudentSort } from "../../actions/dashboard";

import css from "../../../css/portal-dashboard/portal-dashboard-app.less";
import { RootState } from "../../reducers";

interface IProps {
  isFetching: boolean;
  error: IResponse;
  clazzName: string;
  students: any;
  fetchAndObserveData: () => void;
  setStudentSort: (value: any) => void;
  trackEvent: (category: any, action: any, label: any) => void;
  sequenceTree: any;
}

interface IState {
  initialLoading: boolean;
}

class PortalDashboardApp extends React.PureComponent<IProps, IState> {
  constructor(props: IProps) {
    super(props);
    this.state = {
      initialLoading: true
    };
  }

  componentDidMount() {
    const { fetchAndObserveData } = this.props;
    fetchAndObserveData();
  }

  componentDidUpdate(prevProps: IProps) {
    const { initialLoading } = this.state;
    const { isFetching } = this.props;
    if (initialLoading && !isFetching && prevProps.isFetching) {
      this.setState({ initialLoading: false });
    }
  }

  render() {
    const { clazzName, students, error, sequenceTree, setStudentSort, trackEvent } = this.props;
    const { initialLoading } = this.state;
    // In order to list the activities in the correct order,
    // they must be obtained via the child reference in the sequenceTree …
    const activityTrees = sequenceTree && sequenceTree.get("children");
    return (
      <div className={css.portalDashboardApp}>
        <Header/>
        { activityTrees &&
          <div>
            <div className={css.navigation}>
              <ClassNav
                clazzName={clazzName}
                setStudentSort={setStudentSort}
                trackEvent={trackEvent}
              />
              <LevelViewer/>
            </div>
            <StudentList students={students}/>
          </div>
        }
        { error && <DataFetchError error={error} /> }
        { initialLoading && <LoadingIcon /> }
      </div>
    );
  }
}

function mapStateToProps(state: RootState) {
  const data = state.get("data");
  const error = data.get("error");
  const dataDownloaded = !error && !data.get("isFetching");
  return {
    isFetching: data.get("isFetching"),
    error,
    clazzName: dataDownloaded && state.getIn(["report", "clazzName"]),
    students: dataDownloaded && getSortedStudents(state),
    sequenceTree: dataDownloaded && getSequenceTree(state),
  };
}

const mapDispatchToProps = (dispatch: any, ownProps: any): Partial<IProps> => {
{'fraction_non_alphanumeric': 0.14500234631628345, 'fraction_numerical': 0.0, 'mean_word_length': 2.9987492182614135, 'pattern_counts': {'":': 0, '<': 30, '<?xml version=': 0, '>': 36, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3867939', 'n_tokens_mistral': 1800, 'n_tokens_neox': 1859, 'n_words': 430}