pacificclimate/climate-explorer-frontend

View on GitHub
src/components/data-controllers/SingleDataController/SingleDataController.js

Summary

Maintainability
D
1 day
Test Coverage
/*******************************************************************
 * SingleDataController.js - controller component for in-depth numerical
 * visualization of a single variable
 *
 * Receives a model, an experiment, and a variable from its parent,
 * SingleAppController. Manages viewer components that display data as
 * graphs or tables. 
 *
 * Child components vary by whether the selected dataset is a multi year mean
 * climatology. If so:
 *  - a SingleAnnualCycleGraph displaying data with monthly, seasonal, and annual
 *    resolution (as available)
 * 
 *  - a SingleLongTermAverageGraph showing the mean of each climatology
 *    period as a seperate data point.
 *
 *  - a SingleContextGraph similar to the Long Term Average graph, but with
 *    a separate line for each model and simplified presentation.
 *
 *  - an AnomalyAnnualCycleGraph displaying future data as delta from a
 *    "baseline" climatology (usually 1981 - 2010)
 *
 *  - a SingleTimeSliceGraph, which compares all available models
 *    at a single timestamp.
 *
 * If the selected dataset is not a multi year mean:
 *  - a freeform SingleTimeSeriesGraph showing each time point available.
 *
 * A Data Table viewer component showing statistical information for each
 * climatology period or timeseries is also generated. 
 *******************************************************************/

import PropTypes from 'prop-types';

import React from 'react';
import { Row, Col, Panel } from 'react-bootstrap';
import _ from 'lodash';

import SingleAnnualCycleGraph from '../../graphs/SingleAnnualCycleGraph';
import SingleLongTermAveragesGraph from '../../graphs/SingleLongTermAveragesGraph';
import SingleContextGraph from '../../graphs/SingleContextGraph';
import SingleTimeSeriesGraph from '../../graphs/SingleTimeSeriesGraph';
import AnomalyAnnualCycleGraph from '../../graphs/AnomalyAnnualCycleGraph';
import SingleTimeSliceGraph from '../../graphs/SingleTimeSliceGraph';
import {
  singleAnnualCycleTabLabel, changeFromBaselineTabLabel,
  singleLtaTabLabel, modelContextTabLabel, snapshotTabLabel,
  timeSeriesTabLabel,
  graphsPanelLabel,
} from '../../guidance-content/info/InformationItems';

import styles from '../DataController.module.css';
import { MEVSummary } from '../../data-presentation/MEVSummary';
import FlowArrow from '../../data-presentation/FlowArrow';
import GraphTabs from '../GraphTabs';
import StatisticalSummaryTable from '../../StatisticalSummaryTable';


export default class SingleDataController extends React.Component {
  static propTypes = {
    model_id: PropTypes.string,
    variable_id: PropTypes.string,
    experiment: PropTypes.string,
    area: PropTypes.string,
    meta: PropTypes.array,
    contextMeta: PropTypes.array,
    ensemble_name: PropTypes.string,  // TODO: Why is this declared? Remove?
  };

  // TODO: Is this necessary?
  shouldComponentUpdate(nextProps, nextState) {
    // This guards against re-rendering before calls to the data sever alter the
    // state
    // TODO: Consider making shallow comparisons. Deep ones are expensive.
    // If immutable data objects are used (or functionally equivalently,
    // new data objects each time), then shallow comparison works.
    return !(
      _.isEqual(nextProps.meta, this.props.meta) &&
      _.isEqual(nextProps.area, this.props.area)
     );
  }

  // Spec for generating tabs containing various graphs.
  // Property names indicate whether the dataset is a multi-year mean or not.
  // TODO: Pull this out into new component SingleVariableGraphs
  static graphTabsSpecs = {
    mym: [
      { title: singleAnnualCycleTabLabel, graph: SingleAnnualCycleGraph },
      { title: singleLtaTabLabel, graph: SingleLongTermAveragesGraph },
      { title: modelContextTabLabel, graph: SingleContextGraph },
      { title: changeFromBaselineTabLabel, graph: AnomalyAnnualCycleGraph },
      { title: snapshotTabLabel, graph: SingleTimeSliceGraph },
    ],
    notMym: [
      { title: timeSeriesTabLabel, graph: SingleTimeSeriesGraph },
    ],
  };

  render() {
    // TODO: Improve returned item
    if (!_.allDefined(this.props, 'model_id', 'experiment', 'variable_id')) {
      return 'Readying...';
    }

    return (
      // TODO: https://github.com/pacificclimate/climate-explorer-frontend/issues/246
      <div>
        <Panel>
          <Panel.Heading>
            <Panel.Title>
              <Row>
                <Col lg={4}>
                  {graphsPanelLabel}
                </Col>
                <Col lg={8}>
                  <MEVSummary
                    className={styles.mevSummary} {...this.props}
                  />
                </Col>
              </Row>
            </Panel.Title>
          </Panel.Heading>
          <Panel.Body className={styles.data_panel}>
            <GraphTabs
              {...this.props}
              specs={SingleDataController.graphTabsSpecs}
            />
          </Panel.Body>
        </Panel>

        <FlowArrow>filtered datasets</FlowArrow>

        <StatisticalSummaryTable {...this.props} />

      </div>
    );
  }
}