ministryofjustice/moj-product-dashboard

View on GitHub
dashboard/assets/js/containers/product-main.js

Summary

Maintainability
D
2 days
Test Coverage
import React, { Component } from 'react';
import Spinner from 'react-spinkit';
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';

import { Product, getProductData } from '../libs/models';
import { PhaseTag, RagTag, PrintModeToggle, ExportProduct } from '../components/product';
import { ProductOverview } from './product-overview-tab';
import { ProductInfo } from './product-info-tab';
import { ProductPrintMode } from './product-print-mode';

import SeparatorImg from '../../img/separator.png';

export class ProductContainer extends Component {

  constructor(props) {
    super(props);
    this.state = {
      showBurnDown: false,
      hasData: false,
      product: new Product({}),
      timeFrame: 'entire-time-span',
      startDate: null,
      endDate: null,
      isPrintMode: false
    };
    Tabs.setUseDefaultStyles(false);
  }

  componentDidMount() {
    getProductData(this.props.type, this.props.id)
      .then(productJSON => {
        const product = new Product(productJSON);
        this.setState({
          product: product,
          startDate: product.firstDate,
          endDate: product.lastDate,
          hasData: true
        });
      });
  }

  handleBurnDownChange(e) {
    this.setState({showBurnDown: e.target.value == 'burn-down'});
  }

  handleTimeFrameChange(evt) {
    const timeFrame = evt.target.value;
    const state = {timeFrame: timeFrame};
    const { startDate, endDate } = this.state.product.timeFrames[timeFrame];
    // startDate can be null e.g. for 'custome range'
    if (startDate) {
      state.startDate = startDate
    };
    // endDate can be null e.g. for 'custome range'
    if (endDate) {
      state.endDate = endDate
    };
    this.setState(state);
  }

  handleStartDateChange(evt) {
    const startDate = evt.target.value;
    this.setState({
      startDate: startDate,
      timeFrame: this.state.product.matchTimeFrame(startDate, this.state.endDate)
    });
  }

  handleEndDateChange(evt) {
    const endDate = evt.target.value;
    this.setState({
      endDate: endDate,
      timeFrame: this.state.product.matchTimeFrame(this.state.startDate, endDate)
    });
  }

  handleTogglePrintMode(evt) {
    this.setState({isPrintMode: !this.state.isPrintMode});
  }

  normalMode() {
    const product = this.state.product;
    const editButton = () => {
      if (product.meta['can_edit']) {
        return (
          <a className="button" href={ product.meta['admin_url'] }>
            Edit product details
          </a>
        );
      }
      return null;
    }
    return (
      <div>
        <div className="breadcrumbs">
          <ol>
            <li>
              <a href="/">Portfolio Summary</a>
            </li>
            <li style={{ backgroundImage: `url(${SeparatorImg})` }}>
              { product.name }
            </li>
          </ol>
        </div>
        <h1 className="heading-xlarge" id="product-heading">
          <div className="banner">
            <PhaseTag phase={ product.phase } />
            <RagTag rag={ product.rag } />
          </div>
          {product.name}
          { editButton() }
          <p className="font-small"> last updated { product.lastUpdated ? product.lastUpdated : 'never' }
          </p>
        </h1>
        <Tabs className="product-tabs">
          <TabList>
            <Tab><span className="font-small">Overview</span></Tab>
            <Tab><span className="font-small">Product information</span></Tab>
          </TabList>
          <TabPanel>
            <ProductOverview
              product={product}
              onRangeChange={evt => this.handleTimeFrameChange(evt)}
              selectedRange={this.state.timeFrame}
              startDate={this.state.startDate}
              endDate={this.state.endDate}
              onStartDateChange={evt => this.handleStartDateChange(evt)}
              onEndDateChange={evt => this.handleEndDateChange(evt)}
              onBurnDownChange={ (e) => this.handleBurnDownChange(e) }
              showBurnDown={ this.state.showBurnDown }
            />
          </TabPanel>
          <TabPanel>
            <ProductInfo product={ product } />
          </TabPanel>
        </Tabs>
        <hr/>
        <ExportProduct productId={ product.id } />
        <hr/>
        <PrintModeToggle
          isPrintMode={ this.state.isPrintMode }
          onClick = { (evt) => this.handleTogglePrintMode(evt) }
        />
      </div>
    );
  }

  printMode() {
    const product = this.state.product;
    return (
      <div>
        <h1 className="heading-xlarge">
          <div className="banner">
            <PhaseTag phase={ product.phase } />
            <RagTag rag={ product.rag } />
          </div>
          {product.name}
        </h1>
        <ProductPrintMode
          product={product}
          onRangeChange={evt => this.handleTimeFrameChange(evt)}
          selectedRange={this.state.timeFrame}
          startDate={this.state.startDate}
          endDate={this.state.endDate}
          onStartDateChange={evt => this.handleStartDateChange(evt)}
          onEndDateChange={evt => this.handleEndDateChange(evt)}
          onBurnDownChange={ (e) => this.handleBurnDownChange(e) }
          showBurnDown={ this.state.showBurnDown }
        />
        <hr/>
        <PrintModeToggle
          isPrintMode={ this.state.isPrintMode }
          onClick = { (evt) => this.handleTogglePrintMode(evt) }
        />
      </div>
    );
  }

  render() {
    if (typeof this.state.product.name === 'undefined') {
      return (
        <div>
          <div className="spinkit">
            <Spinner spinnerName='three-bounce' />
          </div>
        </div>
      );
    };
    if (this.state.isPrintMode) {
      return this.printMode();
    }
    return this.normalMode();
  }
}

ProductContainer.propTypes = {
  type: React.PropTypes.string.isRequired,
  id: React.PropTypes.string.isRequired
}