<commit_before>/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

/*
* When adding modules to the namespace, ensure that they are added in alphabetical order according to module name.
*/

// MODULES //

var setReadOnly = require( '@stdlib/utils/define-read-only-property' );

// MAIN //

/**
* Top-level namespace.
*
* @namespace ns
*/
var ns = {};

/**
* @name ArrayBuffer
* @memberof ns
* @readonly
* @constructor
* @see {@link module:@stdlib/array/buffer}
*/
setReadOnly( ns, 'ArrayBuffer', require( '@stdlib/array/buffer' ) );

/**
* @name Complex64Array
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/complex64}
*/
setReadOnly( ns, 'Complex64Array', require( '@stdlib/array/complex64' ) );

/**
* @name Complex128Array
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/complex128}
*/
setReadOnly( ns, 'Complex128Array', require( '@stdlib/array/complex128' ) );

/**
* @name convertArray
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/convert}
*/
setReadOnly( ns, 'convertArray', require( '@stdlib/array/convert' ) );

/**
* @name convertArraySame
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/convert-same}
*/
setReadOnly( ns, 'convertArraySame', require( '@stdlib/array/convert-same' ) );

/**
* @name arrayCtors
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/ctors}
*/
setReadOnly( ns, 'arrayCtors', require( '@stdlib/array/ctors' ) );

/**
* @name arrayDataType
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/dtype}
*/
setReadOnly( ns, 'arrayDataType', require( '@stdlib/array/dtype' ) );

/**
* @name arrayDataTypes
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/dtypes}
*/
setReadOnly( ns, 'arrayDataTypes', require( '@stdlib/array/dtypes' ) );

/**
* @name Float32Array
* @memberof ns
* @readonly
* @constructor
* @see {@link module:@stdlib/array/float32}
*/
setReadOnly( ns, 'Float32Array', require( '@stdlib/array/float32' ) );

/**
* @name Float64Array
* @memberof ns
* @readonly
* @constructor
* @see {@link module:@stdlib/array/float64}
*/
setReadOnly( ns, 'Float64Array', require( '@stdlib/array/float64' ) );

/**
* @name iterator2array
* @memberof ns
* @readonly
* @constructor
* @see {@link module:@stdlib/array/from-iterator}
*/
setReadOnly( ns, 'iterator2array', require( '@stdlib/array/from-iterator' ) );

/**
* @name Int8Array
* @memberof ns
* @readonly
* @constructor
* @see {@link module:@stdlib/array/int8}
*/
setReadOnly( ns, 'Int8Array', require( '@stdlib/array/int8' ) );

/**
* @name Int16Array
* @memberof ns
* @readonly
* @constructor
* @see {@link module:@stdlib/array/int16}
*/
setReadOnly( ns, 'Int16Array', require( '@stdlib/array/int16' ) );

/**
* @name Int32Array
* @memberof ns
* @readonly
* @constructor
* @see {@link module:@stdlib/array/int32}
*/
setReadOnly( ns, 'Int32Array', require( '@stdlib/array/int32' ) );

/**
* @name arrayMinDataType
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/min-dtype}
*/
setReadOnly( ns, 'arrayMinDataType', require( '@stdlib/array/min-dtype' ) );

/**
* @name arrayNextDataType
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/next-dtype}
*/
setReadOnly( ns, 'arrayNextDataType', require( '@stdlib/array/next-dtype' ) );

/**
* @name typedarraypool
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/pool}
*/
setReadOnly( ns, 'typedarraypool', require( '@stdlib/array/pool' ) );

/**
* @name arrayPromotionRules
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/promotion-rules}
*/
setReadOnly( ns, 'arrayPromotionRules', require( '@stdlib/array/promotion-rules' ) );

/**
* @name reviveTypedArray
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/reviver}
*/
setReadOnly( ns, 'reviveTypedArray', require( '@stdlib/array/reviver' ) );

/**
* @name arraySafeCasts
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/safe-casts}
*/
setReadOnly( ns, 'arraySafeCasts', require( '@stdlib/array/safe-casts' ) );

/**
* @name arraySameKindCasts
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/same-kind-casts}
*/
setReadOnly( ns, 'arraySameKindCasts', require( '@stdlib/array/same-kind-casts' ) );

/**
* @name arrayShape
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/shape}
*/
setReadOnly( ns, 'arrayShape', require( '@stdlib/array/shape' ) );

/**
* @name SharedArrayBuffer
* @memberof ns
* @readonly
* @constructor
* @see {@link module:@stdlib/array/shared-buffer}
*/
setReadOnly( ns, 'SharedArrayBuffer', require( '@stdlib/array/shared-buffer' ) );

/**
* @name circarray2iterator
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/to-circular-iterator}
*/
setReadOnly( ns, 'circarray2iterator', require( '@stdlib/array/to-circular-iterator' ) );

/**
* @name array2iterator
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/to-iterator}
*/
setReadOnly( ns, 'array2iterator', require( '@stdlib/array/to-iterator' ) );

/**
* @name array2iteratorRight
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/to-iterator-right}
*/
setReadOnly( ns, 'array2iteratorRight', require( '@stdlib/array/to-iterator-right' ) );

/**
* @name typedarray2json
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/to-json}
*/
setReadOnly( ns, 'typedarray2json', require( '@stdlib/array/to-json' ) );

/**
* @name sparsearray2iterator
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/to-sparse-iterator}
*/
setReadOnly( ns, 'sparsearray2iterator', require( '@stdlib/array/to-sparse-iterator' ) );

/**
* @name sparsearray2iteratorRight
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/to-sparse-iterator-right}
*/
setReadOnly( ns, 'sparsearray2iteratorRight', require( '@stdlib/array/to-sparse-iterator-right' ) );

/**
* @name stridedarray2iterator
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/to-strided-iterator}
*/
setReadOnly( ns, 'stridedarray2iterator', require( '@stdlib/array/to-strided-iterator' ) );

/**
* @name arrayview2iterator
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/to-view-iterator}
*/
setReadOnly( ns, 'arrayview2iterator', require( '@stdlib/array/to-view-iterator' ) );

/**
* @name arrayview2iteratorRight
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/to-view-iterator-right}
*/
setReadOnly( ns, 'arrayview2iteratorRight', require( '@stdlib/array/to-view-iterator-right' ) );

/**
* @name typedarray
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/typed}
*/
setReadOnly( ns, 'typedarray', require( '@stdlib/array/typed' ) );

/**
* @name typedarrayComplexCtors
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/typed-complex-ctors}
*/
setReadOnly( ns, 'typedarrayComplexCtors', require( '@stdlib/array/typed-complex-ctors' ) );

/**
* @name typedarrayComplexDataTypes
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/typed-complex-dtypes}
*/
setReadOnly( ns, 'typedarrayComplexDataTypes', require( '@stdlib/array/typed-complex-dtypes' ) );

/**
* @name typedarrayCtors
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/typed-ctors}
*/
setReadOnly( ns, 'typedarrayCtors', require( '@stdlib/array/typed-ctors' ) );

/**
* @name typedarrayDataTypes
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/typed-dtypes}
*/
setReadOnly( ns, 'typedarrayDataTypes', require( '@stdlib/array/typed-dtypes' ) );

/**
* @name Uint8Array
* @memberof ns
* @readonly
* @constructor
* @see {@link module:@stdlib/array/uint8}
*/
setReadOnly( ns, 'Uint8Array', require( '@stdlib/array/uint8' ) );

/**
* @name Uint8ClampedArray
* @memberof ns
* @readonly
* @constructor
* @see {@link module:@stdlib/array/uint8c}
*/
setReadOnly( ns, 'Uint8ClampedArray', require( '@stdlib/array/uint8c' ) );

/**
* @name Uint16Array
* @memberof ns
* @readonly
* @constructor
* @see {@link module:@stdlib/array/uint16}
*/
setReadOnly( ns, 'Uint16Array', require( '@stdlib/array/uint16' ) );

/**
* @name Uint32Array
* @memberof ns
* @readonly
* @constructor
* @see {@link module:@stdlib/array/uint32}
*/
setReadOnly( ns, 'Uint32Array', require( '@stdlib/array/uint32' ) );

/**
* @name constants
* @memberof ns
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/constants/array}
*/
setReadOnly( ns, 'constants', require( '@stdlib/constants/array' ) );

// EXPORTS //

module.exports = ns;
<commit_msg>Update namespace<commit_after>/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

/*
* When adding modules to the namespace, ensure that they are added in alphabetical order according to module name.
*/

// MODULES //

var setReadOnly = require( '@stdlib/utils/define-read-only-property' );

// MAIN //

/**
* Top-level namespace.
*
* @namespace ns
*/
var ns = {};

/**
* @name ArrayBuffer
* @memberof ns
* @readonly
* @constructor
* @see {@link module:@stdlib/array/buffer}
*/
setReadOnly( ns, 'ArrayBuffer', require( '@stdlib/array/buffer' ) );

/**
* @name Complex64Array
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/complex64}
*/
setReadOnly( ns, 'Complex64Array', require( '@stdlib/array/complex64' ) );

/**
* @name Complex128Array
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/complex128}
*/
setReadOnly( ns, 'Complex128Array', require( '@stdlib/array/complex128' ) );

/**
* @name convertArray
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/convert}
*/
setReadOnly( ns, 'convertArray', require( '@stdlib/array/convert' ) );

/**
* @name convertArraySame
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/convert-same}
*/
setReadOnly( ns, 'convertArraySame', require( '@stdlib/array/convert-same' ) );

/**
* @name arrayCtors
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/ctors}
*/
setReadOnly( ns, 'arrayCtors', require( '@stdlib/array/ctors' ) );

/**
* @name arrayDataType
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/dtype}
*/
setReadOnly( ns, 'arrayDataType', require( '@stdlib/array/dtype' ) );

/**
* @name arrayDataTypes
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/dtypes}
*/
setReadOnly( ns, 'arrayDataTypes', require( '@stdlib/array/dtypes' ) );

/**
* @name filledarray
* @memberof ns
* @readonly
* @constructor
* @see {@link module:@stdlib/array/filled}
*/
setReadOnly( ns, 'filledarray', require( '@stdlib/array/filled' ) );

/**
* @name Float32Array
* @memberof ns
* @readonly
* @constructor
* @see {@link module:@stdlib/array/float32}
*/
setReadOnly( ns, 'Float32Array', require( '@stdlib/array/float32' ) );

/**
* @name Float64Array
* @memberof ns
* @readonly
* @constructor
* @see {@link module:@stdlib/array/float64}
*/
setReadOnly( ns, 'Float64Array', require( '@stdlib/array/float64' ) );

/**
* @name iterator2array
* @memberof ns
* @readonly
* @constructor
* @see {@link module:@stdlib/array/from-iterator}
*/
setReadOnly( ns, 'iterator2array', require( '@stdlib/array/from-iterator' ) );

/**
* @name Int8Array
* @memberof ns
* @readonly
* @constructor
* @see {@link module:@stdlib/array/int8}
*/
setReadOnly( ns, 'Int8Array', require( '@stdlib/array/int8' ) );

/**
* @name Int16Array
* @memberof ns
* @readonly
* @constructor
* @see {@link module:@stdlib/array/int16}
*/
setReadOnly( ns, 'Int16Array', require( '@stdlib/array/int16' ) );

/**
* @name Int32Array
* @memberof ns
* @readonly
* @constructor
* @see {@link module:@stdlib/array/int32}
*/
setReadOnly( ns, 'Int32Array', require( '@stdlib/array/int32' ) );

/**
* @name arrayMinDataType
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/min-dtype}
*/
setReadOnly( ns, 'arrayMinDataType', require( '@stdlib/array/min-dtype' ) );

/**
* @name arrayNextDataType
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/next-dtype}
*/
setReadOnly( ns, 'arrayNextDataType', require( '@stdlib/array/next-dtype' ) );

/**
* @name typedarraypool
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/pool}
*/
setReadOnly( ns, 'typedarraypool', require( '@stdlib/array/pool' ) );

/**
* @name arrayPromotionRules
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/promotion-rules}
*/
setReadOnly( ns, 'arrayPromotionRules', require( '@stdlib/array/promotion-rules' ) );

/**
* @name reviveTypedArray
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/reviver}
*/
setReadOnly( ns, 'reviveTypedArray', require( '@stdlib/array/reviver' ) );

/**
* @name arraySafeCasts
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/safe-casts}
*/
setReadOnly( ns, 'arraySafeCasts', require( '@stdlib/array/safe-casts' ) );

/**
* @name arraySameKindCasts
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/same-kind-casts}
*/
setReadOnly( ns, 'arraySameKindCasts', require( '@stdlib/array/same-kind-casts' ) );

/**
* @name arrayShape
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/shape}
*/
setReadOnly( ns, 'arrayShape', require( '@stdlib/array/shape' ) );

/**
* @name SharedArrayBuffer
* @memberof ns
* @readonly
* @constructor
* @see {@link module:@stdlib/array/shared-buffer}
*/
setReadOnly( ns, 'SharedArrayBuffer', require( '@stdlib/array/shared-buffer' ) );

/**
* @name circarray2iterator
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/to-circular-iterator}
*/
setReadOnly( ns, 'circarray2iterator', require( '@stdlib/array/to-circular-iterator' ) );

/**
* @name array2iterator
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/to-iterator}
*/
setReadOnly( ns, 'array2iterator', require( '@stdlib/array/to-iterator' ) );

/**
* @name array2iteratorRight
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/to-iterator-right}
*/
setReadOnly( ns, 'array2iteratorRight', require( '@stdlib/array/to-iterator-right' ) );

/**
* @name typedarray2json
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/to-json}
*/
setReadOnly( ns, 'typedarray2json', require( '@stdlib/array/to-json' ) );

/**
* @name sparsearray2iterator
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/to-sparse-iterator}
*/
setReadOnly( ns, 'sparsearray2iterator', require( '@stdlib/array/to-sparse-iterator' ) );

/**
* @name sparsearray2iteratorRight
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/to-sparse-iterator-right}
*/
setReadOnly( ns, 'sparsearray2iteratorRight', require( '@stdlib/array/to-sparse-iterator-right' ) );

/**
* @name stridedarray2iterator
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/to-strided-iterator}
*/
setReadOnly( ns, 'stridedarray2iterator', require( '@stdlib/array/to-strided-iterator' ) );

/**
* @name arrayview2iterator
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/to-view-iterator}
*/
setReadOnly( ns, 'arrayview2iterator', require( '@stdlib/array/to-view-iterator' ) );

/**
* @name arrayview2iteratorRight
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/to-view-iterator-right}
*/
setReadOnly( ns, 'arrayview2iteratorRight', require( '@stdlib/array/to-view-iterator-right' ) );

/**
* @name typedarray
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/typed}
*/
setReadOnly( ns, 'typedarray', require( '@stdlib/array/typed' ) );

/**
* @name typedarrayComplexCtors
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/typed-complex-ctors}
*/
setReadOnly( ns, 'typedarrayComplexCtors', require( '@stdlib/array/typed-complex-ctors' ) );

/**
* @name typedarrayComplexDataTypes
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/typed-complex-dtypes}
*/
setReadOnly( ns, 'typedarrayComplexDataTypes', require( '@stdlib/array/typed-complex-dtypes' ) );

/**
* @name typedarrayCtors
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/typed-ctors}
*/
setReadOnly( ns, 'typedarrayCtors', require( '@stdlib/array/typed-ctors' ) );

/**
* @name typedarrayDataTypes
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/array/typed-dtypes}
*/
setReadOnly( ns, 'typedarrayDataTypes', require( '@stdlib/array/typed-dtypes' ) );

/**
* @name Uint8Array
* @memberof ns
* @readonly
* @constructor
* @see {@link module:@stdlib/array/uint8}
*/
setReadOnly( ns, 'Uint8Array', require( '@stdlib/array/uint8' ) );

/**
* @name Uint8ClampedArray
* @memberof ns
* @readonly
* @constructor
* @see {@link module:@stdlib/array/uint8c}
*/
setReadOnly( ns, 'Uint8ClampedArray', require( '@stdlib/array/uint8c' ) );

/**
* @name Uint16Array
* @memberof ns
* @readonly
* @constructor
* @see {@link module:@stdlib/array/uint16}
*/
setReadOnly( ns, 'Uint16Array', require( '@stdlib/array/uint16' ) );

/**
* @name Uint32Array
* @memberof ns
* @readonly
* @constructor
* @see {@link module:@stdlib/array/uint32}
*/
setReadOnly( ns, 'Uint32Array', require( '@stdlib/array/uint32' ) );

/**
* @name constants
* @memberof ns
* @readonly
* @type {Namespace}
* @see {@link module:@stdlib/constants/array}
*/
setReadOnly( ns, 'constants', require( '@stdlib/constants/array' ) );

// EXPORTS //

module.exports = ns;
<|endoftext|>


<commit_before>import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import Helmet from 'react-helmet';
import styled from 'styled-components';
import { Control, Form, actions } from 'react-redux-form';
import axios from 'axios';
import { browserHistory } from 'react-router';
import Script from 'react-load-script'

import {fetchBraintreeToken, sendPostcards} from './actions';
import MainHeader from 'components/MainHeader';
import Button from 'components/Button';
import RepCard from './repCard';
import Img from 'components/Img';
import LoadingIndicator from 'components/LoadingIndicator';

const braintree = require('braintree-web');

const RepForm = styled.div`

  .rep-border {
    border: 2px solid red;
    margin-bottom: 2rem;
  }

  text-align: left;

  p {
    line-height: 1.5rem;
    font-size: 1.5rem;
  }

  li {
    overflow: hidden;
  }

  input {
    top: 5rem;
  }

  label {
    margin: 0 auto;
    margin-top: -2rem;
    width: 100%;
  }

  .rep-box {
    a {
      color: #ffffff;
    }

    .rep_content {
      margin-bottom: 2rem;
      margin-right: 2rem;
    }
  }

  .rep_address {
    font-size: 1.2rem;
    font-weight: 300;
  }

  .paypal-btn {
    font-size: 20px;
    margin-left: 5rem;
  }

  .democratic {
    background-color:  ${props => props.theme.democrat_blue};
  }

  .republican {
    background-color: ${props => props.theme.republican_red};
  }

  .independent {
    background-color: ${props => props.theme.independent_teal};
  }
`;

const RepCardBox = styled.div`
  .circle-img {
    overflow: hidden;
    display:inline;
    height: 6rem;
    margin-bottom: 1.5rem;
    border-radius: 50%;
  }
`;

export class Representatives extends React.PureComponent { // eslint-disable-line react/prefer-stateless-function

  constructor(props) {
    super(props);
    this.state = {
      braintreeToken: null,
      loading: false
    }
  }

  componentDidMount() {
    const self = this;
    return axios.get(`/api/payments/client-token`)
    .then(function(res){
      return Promise.resolve(braintree.client.create({
        authorization: res.data.clientToken
      }))
    })
    .then(function(data){
      return self.clientDidCreate(data);
    })
  }

  componentWillUnmount() {
    this.props.dispatch(actions.reset('selectedReps.selected'));
  }

  clientDidCreate(client) {
    const self = this;

    return Promise.resolve(braintree.paypalCheckout.create({
      client: client
    }))
    .then(function(paypalCheckoutInstance) {
      return paypal.Button.render({
        env: 'sandbox',
        locale: 'en_US',

        payment: function() {
          return paypalCheckoutInstance.createPayment({
            flow: 'vault'
          })
        },

        onAuthorize: function(data, actions) {
          return paypalCheckoutInstance.tokenizePayment(data).then(function (payload){

            self.setState({loading: true})

            return self.props.sendPostcards({
              nonce: payload.nonce,
              issueId: self.props.routeParams.id,
              representatives: self.props.selectedReps.selected,
              user: self.props.user
            })
            .then(function(res){
              self.setState({ loading: false });
              browserHistory.push(`/confirmation`)
            })
          })
        },

        onError: function(err){
          console.error('checkout.js error', err);
        }
      }, "#paypal-button")
    })
  }

  createRepCard(representative, index) {
    if (!representative) return;
    const address = representative.address[0];

    return (
      <div className={`col-md-3 col-sm-12 rep_content ${representative.party.toLowerCase()}`} key={representative.name}>

<Control.checkbox model='.selected[]' value={JSON.stringify(representative)} id={`rep_${index}`} className="big_checkbox" />
        <label htmlFor={`rep_${index}`} className="btn">
        <RepCardBox>

{`${representative.name}, ${representative.party[0]}`}

{`${address.line1}, ${address.city}, ${address.state}, ${address.zip}`}

        </RepCardBox>

    )
  }

  createRepCards() {
    return this.props.representatives.map((representative, index) => {
      if (index%2 !== 0) return;

      return (

            {this.createRepCard(representative, index)}
            {this.createRepCard(this.props.representatives[index+1], index+1)}

      )
    })
  }

  render() {
    return (


<commit_before>"use strict";

define(['logManager',
    'loaderProgressBar',
    'js/Constants',
    'js/PanelBase/PanelBaseWithHeader',
    'js/Panels/SplitPanel/SplitPanel',
    'text!js/Visualizers.json',
    'css!/css/Panels/Visualizer/VisualizerPanel'], function (logManager,
                                    LoaderProgressBar,
                                    CONSTANTS,
                                    PanelBaseWithHeader,
                                    SplitPanel,
                                    VisualizersJSON) {

    var VisualizerPanel,
        DEFAULT_VISUALIZER = 'ModelEditor';

    VisualizerPanel = function (layoutManager, params) {
        var options = {};
        //set properties from options
        options[PanelBaseWithHeader.OPTIONS.LOGGER_INSTANCE_NAME] = "Visualizer";
        options[PanelBaseWithHeader.OPTIONS.HEADER_TITLE] = true;

        //call parent's constructor
        PanelBaseWithHeader.apply(this, [options]);

        this._client = params.client;
        this._layoutManager = layoutManager;

        //initialize UI
        this._initialize();

        this._activePanel = {};
        this._activeVisualizer = {};
        this._currentNodeID = null;
        this._visualizers = {};

        this._loadVisualizers();

        this.logger.debug("VisualizerPanel ctor finished");
    };

    //inherit from PanelBaseWithHeader
    _.extend(VisualizerPanel.prototype, PanelBaseWithHeader.prototype);

    VisualizerPanel.prototype._initialize = function () {
        var self = this,
            toolbar = WebGMEGlobal.Toolbar,
            btnIconBase = $('');;

        //set Widget title
        this.setTitle("Visualizer");

        this.$el.addClass('visualizer-panel');

        //add toolbar controls
        toolbar.addSeparator();

        toolbar.addToggleButton({ "title": "Split view ON/OFF",
            "icon": btnIconBase.clone().css('background-image', 'url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAIAAACQKrqGAAAALHRFWHRDcmVhdGlvbiBUaW1lAFR1ZSAxOSBOb3YgMjAxMyAxNjozNjo0NCAtMDYwMKaJVWgAAAAHdElNRQfdCxMWKDLaKUzZAAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAAAAZ0Uk5TAP8A/wD/N1gbfQAAAD5JREFUeNpj/P//PwMqMDExAZJnzpxBE2eBSMABsgo0KSYGogELskloxqBJsWBVgdUNo6bSyFTMZIFpJAQAAMcoMq0xIJLxAAAAAElFTkSuQmCC)'),
            "clickFn": function (data, toggled) {
                self._p2Editor(toggled);
            }});

        this._panel1VisContainer = $('
');
        this._ul1 = $('
');
        this._ul1.attr("data-id", 'p1');
        this._panel1VisContainer.append($('
Panel 1:
'));
        this._panel1VisContainer.append(this._ul1);

        this.$el.append(this._panel1VisContainer);

        this.$el.on('click', 'ul > li:not(.active)', function (event) {
            var vis = $(this).attr("data-id"),
                ul = $(this).parent();
            self._setActiveVisualizer(vis, ul);
            event.stopPropagation();
            event.preventDefault();
        });

        this._client.addEventListener(this._client.events.SELECTEDOBJECT_CHANGED, function (__project, nodeId) {
            self.selectedObjectChanged(nodeId);
        });

        this._splitPanel = new SplitPanel();
        this._layoutManager.addPanel('visualizerSplitPanel', this._splitPanel, 'center');
    };

    VisualizerPanel.prototype._loadVisualizers = function () {
        var self = this;

        this.addRange(JSON.parse(VisualizersJSON), function () {
            self._setActiveVisualizer(DEFAULT_VISUALIZER, self._ul1);
        });
    };

    VisualizerPanel.prototype._setActiveVisualizer = function (visualizer, ul) {
        var PanelClass,
            ControlClass,
            panel = ul.attr('data-id');

        if (this._activeVisualizer[panel] !== visualizer && this._visualizers.hasOwnProperty(visualizer)) {

            //destroy current visualizer
            if (this._activePanel[panel]) {
                this._activePanel[panel].destroy();
            }

            this._activeVisualizer[panel] = visualizer;
            ul.find('> li').removeClass('active');
            ul.find('> li[data-id="' + visualizer + '"]').addClass('active');

            this._activePanel[panel] = null;

            if (this._visualizers[visualizer]) {
                PanelClass = this._visualizers[visualizer].panel;
                if (PanelClass) {
                    this._activePanel[panel] = new PanelClass(this._layoutManager, {'client': this._client});
                    this._splitPanel.setPanel(this._activePanel[panel], panel);
                }

                if (this._currentNodeID || this._currentNodeID === CONSTANTS.PROJECT_ROOT_ID) {
                    if (this._activePanel[panel] && this._activePanel[panel].control && _.isFunction(this._activePanel[panel].control.selectedObjectChanged)) {
                        this._activePanel[panel].control.selectedObjectChanged(this._currentNodeID);
                    }
                }
            }
        }
    };

    VisualizerPanel.prototype._removeLoader = function (li, loaderDiv) {
        if (li.loader) {
            li.loader.stop();
            li.loader.destroy();
            delete li.loader;
        }
        loaderDiv.remove();
    };

    /**********************************************************************/
    /***************     P U B L I C     A P I             ****************/
    /**********************************************************************/

    VisualizerPanel.prototype.add = function (menuDesc, callback) {
        var li = $('

'),
            a = li.find('> a'),
            self = this,
            loaderDiv,
            doCallBack;

        doCallBack = function () {
            if (callback) {
                callback();
            }
        };

        if (menuDesc.DEBUG_ONLY === true && DEBUG !== true) {
            doCallBack();
            return;
        }

        if (this._visualizers[menuDesc.id]) {
            this.logger.warning("A visualizer with the ID '" + menuDesc.id + "' already exists...");
            doCallBack();
        } else {
            li.attr("data-id", menuDesc.id);
            a.text(menuDesc.title);

            this._ul1.append(li);

            if (menuDesc.panel) {

                loaderDiv = $("
", { "class": "vis-loader"});

                li.loader = new LoaderProgressBar({"containerElement": loaderDiv});
                li.loader.start();
                a.append(loaderDiv);

                require([menuDesc.panel],
                    function (panelClass) {
                        self.logger.debug("downloaded: " + menuDesc.panel);
                        self._visualizers[menuDesc.id] = {"panel": panelClass};
                        self._removeLoader(li, loaderDiv);
                        doCallBack();
                    },
                    function (err) {
                        var msg = "Failed to download '" + err.requireModules[0] + "'";
                        //for any error store undefined in the list and the default decorator will be used on the canvas
                        self.logger.error(msg);
                        a.append(' ');
                        self._removeLoader(li, loaderDiv);
                        doCallBack();
                    });
            } else {
                a.append(' ');

                this.logger.warning("The visualizer with the ID '" + menuDesc.id + "' is missing 'panel' or 'control'");

                doCallBack();
            }
        }
    };

    VisualizerPanel.prototype.addRange = function (menuDescList, callback) {
        var queueLen = 0,
            len = menuDescList.length,
            i,
            callbackWrap;

        if (callback) {
            callbackWrap = function () {
                queueLen -= 1;
                if (queueLen === 0) {
                    callback();
                }
            }
        }

        for (i = 0; i < len; i += 1) {
            queueLen += 1;
            this.add(menuDescList[i], callbackWrap);
        }
    };

    VisualizerPanel.prototype.selectedObjectChanged = function (currentNodeId) {
        this._currentNodeID = currentNodeId;
    };

    VisualizerPanel.prototype._p2Editor = function (enabled) {
        if (enabled) {
            //show 2 panels
            this._panel2VisContainer = this._panel1VisContainer.clone();
            this._panel2VisContainer.find('ul').attr("data-id", 'p2');
            this._panel2VisContainer.find('.pp').text('Panel 2:');
            this.$el.append(this._panel2VisContainer);
            //find the selected on
            var activeLi = this._panel2VisContainer.find('ul > li.active'),
                vis = activeLi.attr("data-id"),
                ul = activeLi.parent();
            this._setActiveVisualizer(vis, ul);
        } else {
            //destroy current controller and visualizer
            var panel = 'p2';
            if (this._activePanel[panel] && this._activePanel[panel].destroy) {
                this._activePanel[panel].destroy();
            }

            this._activePanel[panel] = null;
            this._activeVisualizer[panel] = null;

            this._panel2VisContainer.remove();
            this._panel2VisContainer = undefined;
            this._splitPanel.deletePanel('p2');
        }
    };

    return VisualizerPanel;
});
<commit_msg>disable 2panels on ProjectOpen, ProjectClose, BranchChanged<commit_after>"use strict";

define(['logManager',
    'loaderProgressBar',
    'js/Constants',
    'js/PanelBase/PanelBaseWithHeader',
    'js/Panels/SplitPanel/SplitPanel',
    'text!js/Visualizers.json',
    'css!/css/Panels/Visualizer/VisualizerPanel'], function (logManager,
                                    LoaderProgressBar,
                                    CONSTANTS,
                                    PanelBaseWithHeader,
                                    SplitPanel,
                                    VisualizersJSON) {

    var VisualizerPanel,
        DEFAULT_VISUALIZER = 'ModelEditor';

    VisualizerPanel = function (layoutManager, params) {
        var options = {};
        //set properties from options
        options[PanelBaseWithHeader.OPTIONS.LOGGER_INSTANCE_NAME] = "Visualizer";
        options[PanelBaseWithHeader.OPTIONS.HEADER_TITLE] = true;

        //call parent's constructor
        PanelBaseWithHeader.apply(this, [options]);

        this._client = params.client;
        this._layoutManager = layoutManager;

        //initialize UI
        this._initialize();

        this._activePanel = {};
        this._activeVisualizer = {};
        this._currentNodeID = null;
        this._visualizers = {};

        this._loadVisualizers();

        this.logger.debug("VisualizerPanel ctor finished");
    };

    //inherit from PanelBaseWithHeader
    _.extend(VisualizerPanel.prototype, PanelBaseWithHeader.prototype);

    VisualizerPanel.prototype._initialize = function () {
        var self = this,
            toolbar = WebGMEGlobal.Toolbar,
            btnIconBase = $('');;

        //set Widget title
        this.setTitle("Visualizer");

        this.$el.addClass('visualizer-panel');

        //add toolbar controls
        toolbar.addSeparator();

        toolbar.addToggleButton({ "title": "Split view ON/OFF",
            "icon": btnIconBase.clone().css('background-image', 'url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAIAAACQKrqGAAAALHRFWHRDcmVhdGlvbiBUaW1lAFR1ZSAxOSBOb3YgMjAxMyAxNjozNjo0NCAtMDYwMKaJVWgAAAAHdElNRQfdCxMWKDLaKUzZAAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAAAAZ0Uk5TAP8A/wD/N1gbfQAAAD5JREFUeNpj/P//PwMqMDExAZJnzpxBE2eBSMABsgo0KSYGogELskloxqBJsWBVgdUNo6bSyFTMZIFpJAQAAMcoMq0xIJLxAAAAAElFTkSuQmCC)'),
            "clickFn": function (data, toggled) {
                self._p2Editor(toggled);
            }});

        this._panel1VisContainer = $('
');
        this._ul1 = $('
');
        this._ul1.attr("data-id", 'p1');
        this._panel1VisContainer.append($('
Panel 1:
'));
        this._panel1VisContainer.append(this._ul1);

        this.$el.append(this._panel1VisContainer);

        this.$el.on('click', 'ul > li:not(.active)', function (event) {
            var vis = $(this).attr("data-id"),
                ul = $(this).parent();
            self._setActiveVisualizer(vis, ul);
            event.stopPropagation();
            event.preventDefault();
        });

        this._client.addEventListener(this._client.events.SELECTEDOBJECT_CHANGED, function (__project, nodeId) {
            self.selectedObjectChanged(nodeId);
        });

        this._client.addEventListener(this._client.events.PROJECT_CLOSED, function (__project, nodeId) {
            self._p2Editor(false);
        });

        this._client.addEventListener(this._client.events.PROJECT_OPENED, function (__project, nodeId) {
            self._p2Editor(false);
        });

        this._client.addEventListener(this._client.events.BRANCH_CHANGED, function (__project, nodeId) {
            self._p2Editor(false);
        });

        this._splitPanel = new SplitPanel();
        this._layoutManager.addPanel('visualizerSplitPanel', this._splitPanel, 'center');
    };

    VisualizerPanel.prototype._loadVisualizers = function () {
        var self = this;

        this.addRange(JSON.parse(VisualizersJSON), function () {
            self._setActiveVisualizer(DEFAULT_VISUALIZER, self._ul1);
        });
    };

    VisualizerPanel.prototype._setActiveVisualizer = function (visualizer, ul) {
        var PanelClass,
            ControlClass,
            panel = ul.attr('data-id');

        if (this._activeVisualizer[panel] !== visualizer && this._visualizers.hasOwnProperty(visualizer)) {

            //destroy current visualizer
            if (this._activePanel[panel]) {
                this._activePanel[panel].destroy();
            }

            this._activeVisualizer[panel] = visualizer;
            ul.find('> li').removeClass('active');
            ul.find('> li[data-id="' + visualizer + '"]').addClass('active');

            this._activePanel[panel] = null;

            if (this._visualizers[visualizer]) {
                PanelClass = this._visualizers[visualizer].panel;
                if (PanelClass) {
                    this._activePanel[panel] = new PanelClass(this._layoutManager, {'client': this._client});
                    this._splitPanel.setPanel(this._activePanel[panel], panel);
                }

                if (this._currentNodeID || this._currentNodeID === CONSTANTS.PROJECT_ROOT_ID) {
                    if (this._activePanel[panel] && this._activePanel[panel].control && _.isFunction(this._activePanel[panel].control.selectedObjectChanged)) {
                        this._activePanel[panel].control.selectedObjectChanged(this._currentNodeID);
                    }
                }
            }
        }
    };

    VisualizerPanel.prototype._removeLoader = function (li, loaderDiv) {
        if (li.loader) {
            li.loader.stop();
            li.loader.destroy();
            delete li.loader;
        }
        loaderDiv.remove();
    };

    /**********************************************************************/
    /***************     P U B L I C     A P I             ****************/
    /**********************************************************************/

    VisualizerPanel.prototype.add = function (menuDesc, callback) {
        var li = $('

'),
            a = li.find('> a'),
            self = this,
            loaderDiv,
            doCallBack;

        doCallBack = function () {
            if (callback) {
                callback();
            }
        };

        if (menuDesc.DEBUG_ONLY === true && DEBUG !== true) {
            doCallBack();
            return;
        }

        if (this._visualizers[menuDesc.id]) {
            this.logger.warning("A visualizer with the ID '" + menuDesc.id + "' already exists...");
            doCallBack();
        } else {
            li.attr("data-id", menuDesc.id);
            a.text(menuDesc.title);

            this._ul1.append(li);

            if (menuDesc.panel) {

                loaderDiv = $("
", { "class": "vis-loader"});

                li.loader = new LoaderProgressBar({"containerElement": loaderDiv});
                li.loader.start();
                a.append(loaderDiv);

                require([menuDesc.panel],
                    function (panelClass) {
                        self.logger.debug("downloaded: " + menuDesc.panel);
                        self._visualizers[menuDesc.id] = {"panel": panelClass};
                        self._removeLoader(li, loaderDiv);
                        doCallBack();
                    },
                    function (err) {
                        var msg = "Failed to download '" + err.requireModules[0] + "'";
                        //for any error store undefined in the list and the default decorator will be used on the canvas
                        self.logger.error(msg);
                        a.append(' ');
                        self._removeLoader(li, loaderDiv);
                        doCallBack();
                    });
            } else {
                a.append(' ');

                this.logger.warning("The visualizer with the ID '" + menuDesc.id + "' is missing 'panel' or 'control'");

                doCallBack();
            }
        }
    };

    VisualizerPanel.prototype.addRange = function (menuDescList, callback) {
        var queueLen = 0,
            len = menuDescList.length,
            i,
            callbackWrap;

        if (callback) {
            callbackWrap = function () {
                queueLen -= 1;
                if (queueLen === 0) {
                    callback();
                }
            }
        }

        for (i = 0; i < len; i += 1) {
            queueLen += 1;
            this.add(menuDescList[i], callbackWrap);
        }
    };

    VisualizerPanel.prototype.selectedObjectChanged = function (currentNodeId) {
        this._currentNodeID = currentNodeId;
    };

    VisualizerPanel.prototype._p2Editor = function (enabled) {
        if (enabled) {
            //show 2 panels
            this._panel2VisContainer = this._panel1VisContainer.clone();
            this._panel2VisContainer.find('ul').attr("data-id", 'p2');
            this._panel2VisContainer.find('.pp').text('Panel 2:');
            this.$el.append(this._panel2VisContainer);
            //find the selected on
            var activeLi = this._panel2VisContainer.find('ul > li.active'),
                vis = activeLi.attr("data-id"),
                ul = activeLi.parent();
            this._setActiveVisualizer(vis, ul);
        } else {
            //destroy current controller and visualizer
            var panel = 'p2';
            if (this._activePanel[panel] && this._activePanel[panel].destroy) {
                this._activePanel[panel].destroy();
            }

            this._activePanel[panel] = null;
            this._activeVisualizer[panel] = null;

            if (this._panel2VisContainer) {
                this._panel2VisContainer.remove();
                this._panel2VisContainer = undefined;
                this._splitPanel.deletePanel('p2');
            }
        }
    };

    return VisualizerPanel;
});
<|endoftext|>


<commit_before>import React from "react";
import styled from "@emotion/styled";
import button from "mdlean/lib/button";
import Row from "components/Row";
import Title from "components/Title";
import cardComponent from "./cardComponent";
import Content from "./content";

export default async context => {
  const { tr, palette } = context;
  const CardIcon = cardComponent(context);
  const { features, frontend, backend, tools } = Content();

  const Section = styled("section")(() => ({
    borderTop: `1px solid ${palette.borderColor}`,
    paddingBottom: 30
  }));

  const HeaderView = styled("section")({
    padding: 20
  });

  function Header() {
    const Button = button(context);
    return (
      <HeaderView>

{tr.t("StarHackIt")}

{tr.t("A Full Stack Web Application Starter Kit")}

{tr.t("Built with React, Node, data backed by SQL")}

        <Button
          raised
          label="Clone the code on GitHub"
          href="https://github.com/FredericHeem/starhackit"
          icon={

          }
        />

      </HeaderView>
    );
  }

  function Features() {
    return (

        <Title>{tr.t("Features")}</Title>
        <Row className="text-center">
          {features.map((card, key) => <CardIcon key={key} {...card} />)}
        </Row>

    );
  }

  const E2eImg = styled("img")({
    width: "100%",
    maxWidth: "1200"
  });

  function End2End() {
    return (

        <Title>{tr.t("End to End Testing")}</Title>
        <E2eImg
          alt="functional-testing"
          src="https://raw.githubusercontent.com/FredericHeem/gifs/master/starhackit-functional-testing.gif"
        />

    );
  }

  function Frontend() {
    return (

        <Title>{tr.t("Frontend - User Interface")}</Title>
        <Row>
          {frontend.map((card, key) => <CardIcon key={key} {...card} />)}
        </Row>

    );
  }

  function Backend() {
    return (

        <Title>{tr.t("Backend - API Server")}</Title>
        <Row>
          {backend.map((card, key) => <CardIcon key={key} {...card} />)}
        </Row>

    );
  }

  function Tools() {
    return (

        <Title>{tr.t("Developer Tools")}</Title>
        <Row>{tools.map((card, key) => <CardIcon key={key} {...card} />)}</Row>

    );
  }

  function LandingScreen() {
    return (

        <Features />
        <End2End />
        <Frontend />
        <Backend />
        <Tools />

    );
  }

  return LandingScreen;
};
<commit_msg>fix landing page<commit_after>import React from "react";
import styled from "@emotion/styled";
import button from "mdlean/lib/button";
import Row from "components/Row";
import Title from "components/Title";
import cardComponent from "./cardComponent";
import Content from "./content";

export default context => {
  const { tr, palette } = context;
  const CardIcon = cardComponent(context);
  const { features, frontend, backend, tools } = Content();

  const Section = styled("section")(() => ({
    borderTop: `1px solid ${palette.borderColor}`,
    paddingBottom: 30
  }));

  const HeaderView = styled("section")({
    padding: 20
  });

  function Header() {
    const Button = button(context);
    return (
      <HeaderView>

{tr.t("StarHackIt")}

{tr.t("A Full Stack Web Application Starter Kit")}

{tr.t("Built with React, Node, data backed by SQL")}

        <Button
          raised
          label="Clone the code on GitHub"
          href="https://github.com/FredericHeem/starhackit"
          icon={

          }
        />

      </HeaderView>
    );
  }

  function Features() {
    return (

        <Title>{tr.t("Features")}</Title>
        <Row className="text-center">
          {features.map((card, key) => <CardIcon key={key} {...card} />)}
        </Row>

    );
  }

  const E2eImg = styled("img")({
    width: "100%",
    maxWidth: "1200"
  });

  function End2End() {
    return (

        <Title>{tr.t("End to End Testing")}</Title>
        <E2eImg
          alt="functional-testing"
          src="https://raw.githubusercontent.com/FredericHeem/gifs/master/starhackit-functional-testing.gif"
        />

    );
  }

  function Frontend() {
    return (

        <Title>{tr.t("Frontend - User Interface")}</Title>
        <Row>
          {frontend.map((card, key) => <CardIcon key={key} {...card} />)}
        </Row>

    );
  }

  function Backend() {
    return (

        <Title>{tr.t("Backend - API Server")}</Title>
        <Row>
          {backend.map((card, key) => <CardIcon key={key} {...card} />)}
        </Row>

    );
  }

  function Tools() {
    return (

        <Title>{tr.t("Developer Tools")}</Title>
        <Row>{tools.map((card, key) => <CardIcon key={key} {...card} />)}</Row>

    );
  }

  function LandingScreen() {
    return (

        <Features />
        <End2End />
        <Frontend />
        <Backend />
        <Tools />

    );
  }

  return LandingScreen;
};
<|endoftext|>


<commit_before>import React from "react";
import { filter, map } from "lodash-es";
import { Row, Col, ListGroup, Modal } from "react-bootstrap";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
import { push } from "react-router-redux";

import { findFiles } from "../../files/actions";
import { createSubtraction } from "../actions";
import { Button, Icon, Input, ListGroupItem, RelativeTime } from "../../base";
import {routerLocationHasState} from "../../utils";

class SubtractionFileItem extends React.Component {

    handleClick = () => {
        this.props.onClick(this.props.id);
    };

    render () {

        const { active, name, uploaded_at, user } = this.props;

        return (
            <ListGroupItem active={active} onClick={this.handleClick}>
                <Row>
                    <Col xs={7}>
                        {name}
                    </Col>
                    <Col xs={5}>
                        Uploaded <RelativeTime time={uploaded_at} /> by {user.id}
                    </Col>
                </Row>
            </ListGroupItem>
        );
    }
}

const getInitialState = () => ({
    subtractionId: "",
    fileId: "",
    error: ""
});

class CreateSubtraction extends React.Component {

    constructor (props) {
        super(props);
        this.state = getInitialState();
    }

    handleChange = (e) => {
        this.setState({
            subtractionId: e.target.value,
            error: ""
        });
    };

    handleModalEnter = () => {
        this.props.onFindFiles();
    };

    handleModalExited = () => {
        this.setState(getInitialState());
    };

    handleSelectFile = (fileId) => {
        this.setState({
            fileId: fileId === this.state.fileId ? "" : fileId
        });
    };

    handleSubmit = (e) => {
        e.preventDefault();

        if (this.state.subtractionId) {
            this.props.onCreate(this.state);
        } else {
            this.setState({error: "Required"});
        }
    };

    render () {

        const files = filter(this.props.files, {type: "subtraction"});

        let fileComponents;

        if (files.length) {
            fileComponents = map(files, file =>
                <SubtractionFileItem
                    key={file.id}
                    {...file}
                    active={file.id === this.state.fileId}
                    onClick={this.handleSelectFile}
                />
            );
        } else {
            fileComponents = (
                <ListGroupItem className="text-center">
                    <Icon name="info" /> No files found. <Link to="/subtraction/files">Upload some</Link>.
                </ListGroupItem>
            );
        }

        return (
            <Modal
                bsSize="large"
                show={this.props.show}
                onHide={this.props.onHide}
                onEnter={this.handleModalEnter}
                onExited={this.handleModalExited}
            >

                <Modal.Header>
                    Create Subtraction
                </Modal.Header>

                <form onSubmit={this.handleSubmit}>
                    <Modal.Body>
                        <Input
                            type="text"
                            label="Unique Name"
                            value={this.state.subtractionId}
                            onChange={this.handleChange}
                            error={this.state.error}
                        />

Files

                        <ListGroup>
                            {fileComponents}
                        </ListGroup>
                    </Modal.Body>

                    <Modal.Footer className="modal-footer">
                        <Button
                            type="submit"
                            bsStyle="primary"
                            icon="play"
                            pullRight
                        >
                            Start
                        </Button>
                    </Modal.Footer>
                </form>
            </Modal>
        );
    }
}

const mapStateToProps = (state) => ({
    show: routerLocationHasState(state, "createSubtraction"),
    files: state.files.documents
});

const mapDispatchToProps = (dispatch) => ({

    onCreate: ({ subtractionId, fileId }) => {
        dispatch(createSubtraction(subtractionId, fileId));
    },

    onFindFiles: () => {
        dispatch(findFiles("subtraction"));
    },

    onHide: () => {
        dispatch(push({...window.location, state: {createSubtraction: false}}));
    }

});

const Container = connect(mapStateToProps, mapDispatchToProps)(CreateSubtraction);

export default Container;
<commit_msg>Edit create subtraction input errors<commit_after>import React from "react";
import { filter, map, find } from "lodash-es";
import { Row, Col, ListGroup, Modal } from "react-bootstrap";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
import { push } from "react-router-redux";

import { findFiles } from "../../files/actions";
import { createSubtraction } from "../actions";
import { Button, Icon, Input, ListGroupItem, RelativeTime } from "../../base";
import {routerLocationHasState} from "../../utils";

class SubtractionFileItem extends React.Component {

    handleClick = () => {
        this.props.onClick(this.props.id);
    };

    render () {

        const { active, name, uploaded_at, user } = this.props;

        return (
            <ListGroupItem active={active} onClick={this.handleClick}>
                <Row>
                    <Col xs={7}>
                        {name}
                    </Col>
                    <Col xs={5}>
                        Uploaded <RelativeTime time={uploaded_at} /> by {user.id}
                    </Col>
                </Row>
            </ListGroupItem>
        );
    }
}

const getInitialState = () => ({
    subtractionId: "",
    fileId: "",
    errors: []
});

class CreateSubtraction extends React.Component {

    constructor (props) {
        super(props);
        this.state = getInitialState();
    }

    handleChange = (e) => {
        this.setState({
            subtractionId: e.target.value,
            errors: []
        });
    };

    handleModalEnter = () => {
        this.props.onFindFiles();
    };

    handleModalExited = () => {
        this.setState(getInitialState());
    };

    handleSelectFile = (fileId) => {
        this.setState({
            fileId: fileId === this.state.fileId ? "" : fileId
        });
    };

    handleSubmit = (e) => {
        e.preventDefault();

        const errors = [];

        if (this.state.subtractionId && this.state.fileId) {

            this.props.onCreate(this.state);

        } else {

            if (!this.state.subtractionId) {
                errors.push({
                    id: 0,
                    message: "Required Field"
                });
            }

            if (!this.state.fileId) {
                errors.push({
                    id: 1,
                    message: "Please select a file"
                });
            }
        }

        this.setState({errors});

    };

    render () {

        const files = filter(this.props.files, {type: "subtraction"});

        let fileComponents;

        if (files.length) {
            fileComponents = map(files, file =>
                <SubtractionFileItem
                    key={file.id}
                    {...file}
                    active={file.id === this.state.fileId}
                    onClick={this.handleSelectFile}
                />
            );
        } else {
            fileComponents = (
                <ListGroupItem className="text-center">
                    <Icon name="info" /> No files found. <Link to="/subtraction/files">Upload some</Link>.
                </ListGroupItem>
            );
        }

        const errorName = find(this.state.errors, ["id", 0]) ? find(this.state.errors, ["id", 0]).message : null;
        const errorFile = find(this.state.errors, ["id", 1]) ? find(this.state.errors, ["id", 1]).message : null;

        const fileGroupStyle = errorFile ? "red" : "white";

        let errorMessage;

        if (errorFile) {
            errorMessage = (

                    {errorFile}

            );
        }

        return (
            <Modal
                bsSize="large"
                show={this.props.show}
                onHide={this.props.onHide}
                onEnter={this.handleModalEnter}
                onExited={this.handleModalExited}
            >

                <Modal.Header>
                    Create Subtraction
                </Modal.Header>

                <form onSubmit={this.handleSubmit}>
                    <Modal.Body style={{margin: "0 0 10px 0"}}>
                        <Input
                            type="text"
                            label="Unique Name"
                            value={this.state.subtractionId}
                            onChange={this.handleChange}
                            error={errorName}
                        />

Files

                        <ListGroup style={{border: `1px solid ${fileGroupStyle}`, margin: "0"}}>
                            {fileComponents}
                        </ListGroup>
                        {errorMessage}
                    </Modal.Body>

                    <Modal.Footer className="modal-footer">
                        <Button
                            type="submit"
                            bsStyle="primary"
                            icon="play"
                            pullRight
                        >
                            Start
                        </Button>
                    </Modal.Footer>
                </form>
            </Modal>
        );
    }
}

const mapStateToProps = (state) => ({
    show: routerLocationHasState(state, "createSubtraction"),
    files: state.files.documents
});

const mapDispatchToProps = (dispatch) => ({

    onCreate: ({ subtractionId, fileId }) => {
        dispatch(createSubtraction(subtractionId, fileId));
    },

    onFindFiles: () => {
        dispatch(findFiles("subtraction"));
    },

    onHide: () => {
        dispatch(push({...window.location, state: {createSubtraction: false}}));
    }

});

const Container = connect(mapStateToProps, mapDispatchToProps)(CreateSubtraction);

export default Container;
<|endoftext|>


<commit_before>var cdb = require('cartodb.js');
var DatasetsItem = require('../../dashboard/datasets/datasets_item');
var navigateThroughRouter = require('../../common/view_helpers/navigate_through_router');
var UploadConfig = require('../../common/background_polling/models/upload_config');
var Utils = require('cdb.Utils');
var pluralizeString = require('../../common/view_helpers/pluralize_string');

/**
 *  Remote dataset item view
 *
 */

module.exports = DatasetsItem.extend({

  tagName: 'li',
  className: 'DatasetsList-item',

  events: {
    'click .js-tag-link': navigateThroughRouter,
    'click': '_selectDataset'
  },

  initialize: function() {
    this.user = this.options.user;
    this.router = this.options.router;
    this.template = cdb.templates.getTemplate('dashboard/views/remote_datasets_item');
    this.table = new cdb.admin.CartoDBTableMetadata(this.model.get('external_source'));

    this._initBinds();
  },

  render: function() {
    var vis = this.model;
    var table = this.table;
    var tags = vis.get('tags') || [];
    var description = vis.get('description') && Utils.stripHTML(markdown.toHTML(vis.get('description'))) || '';
    var source = vis.get('source') && markdown.toHTML(vis.get('source')) || '';

    var d = {
      isRaster:                vis.get('kind') === 'raster',
      geometryType:            table.statsGeomColumnTypes().length > 0 ? table.statsGeomColumnTypes()[0] : '',
      title:                   vis.get('name'),
      source:                  source,
      description:             description,
      timeDiff:                moment(vis.get('updated_at')).fromNow(),
      tags:                    tags,
      tagsCount:               tags.length,
      router:                  this.router,
      maxTagsToShow:           3,
      canImportDataset:        this._canImportDataset(),
      rowCount:                undefined,
      datasetSize:             undefined,
      fromExternalSource:      vis.get("synchronization") ? vis.get("synchronization").from_external_source : false
    };

    var rowCount = table.get('row_count');
    if (rowCount >= 0) {
      d.rowCount = ( rowCount < 10000 ? Utils.formatNumber(rowCount) : Utils.readizableNumber(rowCount) );
      d.pluralizedRows = pluralizeString('Row', rowCount);
    }

    var datasetSize = table.get('size');
    if (datasetSize >= 0) {
      d.datasetSize = Utils.readablizeBytes(datasetSize, true);
    }

    this.$el.html(this.template(d));
    this._setItemClasses();
    this._renderTooltips();

    return this;
  },

  _renderTooltips: function() {
    this.addView(
      new cdb.common.TipsyTooltip({
        el: this.$('.DatasetsList-itemStatus'),
        title: function(e) {
          return $(this).attr('data-title')
        }
      })
    )
  },

  _setItemClasses: function() {
    // Item selected?
    this.$el[ this.model.get('selected') ? 'addClass' : 'removeClass' ]('is--selected');
    // Check if it is selectable
    this.$el[ this._canImportDataset() ? 'addClass' : 'removeClass' ]('DatasetsList-item--selectable');
    // Check if it is importable
    this.$el[ this._canImportDataset() ? 'removeClass' : 'addClass' ]('DatasetsList-item--banned');
  },

  _canImportDataset: function() {
    var table_size = this.table.get('size') || 0;
    return (
        this.user.get('remaining_byte_quota') * UploadConfig.fileTimesBigger >= table_size &&
        this.user.get('limits')['import_file_size'] > table_size
      );
  },

  _selectDataset: function(ev) {
    if (ev.target.tagName !== 'A') {
      // If it fits on user quota, user can select it
      if (this._canImportDataset()) {
        this.killEvent(ev);
        this.model.set('selected', !this.model.get('selected'));
      }
    }
  }

});
<commit_msg>refactor line as suggested by xavijam<commit_after>var cdb = require('cartodb.js');
var DatasetsItem = require('../../dashboard/datasets/datasets_item');
var navigateThroughRouter = require('../../common/view_helpers/navigate_through_router');
var UploadConfig = require('../../common/background_polling/models/upload_config');
var Utils = require('cdb.Utils');
var pluralizeString = require('../../common/view_helpers/pluralize_string');

/**
 *  Remote dataset item view
 *
 */

module.exports = DatasetsItem.extend({

  tagName: 'li',
  className: 'DatasetsList-item',

  events: {
    'click .js-tag-link': navigateThroughRouter,
    'click': '_selectDataset'
  },

  initialize: function() {
    this.user = this.options.user;
    this.router = this.options.router;
    this.template = cdb.templates.getTemplate('dashboard/views/remote_datasets_item');
    this.table = new cdb.admin.CartoDBTableMetadata(this.model.get('external_source'));

    this._initBinds();
  },

  render: function() {
    var vis = this.model;
    var table = this.table;
    var tags = vis.get('tags') || [];
    var description = vis.get('description') && Utils.stripHTML(markdown.toHTML(vis.get('description'))) || '';
    var source = vis.get('source') && markdown.toHTML(vis.get('source')) || '';

    var d = {
      isRaster:                vis.get('kind') === 'raster',
      geometryType:            table.statsGeomColumnTypes().length > 0 ? table.statsGeomColumnTypes()[0] : '',
      title:                   vis.get('name'),
      source:                  source,
      description:             description,
      timeDiff:                moment(vis.get('updated_at')).fromNow(),
      tags:                    tags,
      tagsCount:               tags.length,
      router:                  this.router,
      maxTagsToShow:           3,
      canImportDataset:        this._canImportDataset(),
      rowCount:                undefined,
      datasetSize:             undefined,
      fromExternalSource:      ""
    };

    var rowCount = table.get('row_count');
    if (rowCount >= 0) {
      d.rowCount = ( rowCount < 10000 ? Utils.formatNumber(rowCount) : Utils.readizableNumber(rowCount) );
      d.pluralizedRows = pluralizeString('Row', rowCount);
    }

    if (!_.isEmpty(vis.get("synchronization"))) {
      d.fromExternalSource = vis.get("synchronization").from_external_source;
    }

    var datasetSize = table.get('size');
    if (datasetSize >= 0) {
      d.datasetSize = Utils.readablizeBytes(datasetSize, true);
    }

    this.$el.html(this.template(d));
    this._setItemClasses();
    this._renderTooltips();

    return this;
  },

  _renderTooltips: function() {
    this.addView(
      new cdb.common.TipsyTooltip({
        el: this.$('.DatasetsList-itemStatus'),
        title: function(e) {
          return $(this).attr('data-title')
        }
      })
    )
  },

  _setItemClasses: function() {
    // Item selected?
    this.$el[ this.model.get('selected') ? 'addClass' : 'removeClass' ]('is--selected');
    // Check if it is selectable
    this.$el[ this._canImportDataset() ? 'addClass' : 'removeClass' ]('DatasetsList-item--selectable');
    // Check if it is importable
    this.$el[ this._canImportDataset() ? 'removeClass' : 'addClass' ]('DatasetsList-item--banned');
  },

  _canImportDataset: function() {
    var table_size = this.table.get('size') || 0;
    return (
        this.user.get('remaining_byte_quota') * UploadConfig.fileTimesBigger >= table_size &&
        this.user.get('limits')['import_file_size'] > table_size
      );
  },

  _selectDataset: function(ev) {
    if (ev.target.tagName !== 'A') {
      // If it fits on user quota, user can select it
      if (this._canImportDataset()) {
        this.killEvent(ev);
        this.model.set('selected', !this.model.get('selected'));
      }
    }
  }

});
<|endoftext|>


<commit_before>'use strict';

// MODULES //

var join = require( 'path' ).join;
var tape = require( 'tape' );
var noop = require( '@stdlib/utils/noop' );
var readFileSync = require( '@stdlib/fs/read-file' ).sync;
var createElement = require( './../lib' );

// FUNCTIONS //

function setup() {
	return {
		'className': 'equation',
		'align': 'center',
		'raw': 'y = mx + b',
		'label': 'eq:line'
	};
}

// TESTS //

tape( 'main export is a function', function test( t ) {
	t.equal( typeof createElement, 'function', 'main export is a function' );
	t.end();
});

tape( 'the function throws an error if provided an invalid `options` argument', function test( t ) {
	var values;
	var i;

	values = [
		'5',
		5,
		NaN,
		null,
		void 0,
		true,
		[],
		function noop() {}
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws when provided ' + values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			createElement( value, noop );
		};
	}
});

tape( 'the function throws an error if provided an invalid option', function test( t ) {
	var values;
	var i;

	values = [
		5,
		NaN,
		null,
		void 0,
		true,
		false,
		[],
		{},
		function noop() {}
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws when provided ' + values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			var opts = setup();
			opts.raw = value;
			createElement( opts, noop );
		};
	}
});

tape( 'the function throws an error if not provided a callback function (no options)', function test( t ) {
	var values;
	var i;

	values = [
		'5',
		5,
		NaN,
		null,
		void 0,
		true,
		false,
		[],
		{}
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws when provided ' + values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			createElement( value );
		};
	}
});

tape( 'the function throws an error if not provided a callback function (options)', function test( t ) {
	var values;
	var i;

	values = [
		'5',
		5,
		NaN,
		null,
		void 0,
		true,
		false,
		[],
		{}
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws when provided ' + values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			createElement( {}, value );
		};
	}
});

tape( 'the function returns an HTML string for inlining an SVG equation in Markdown', function test( t ) {
	var expected = readFileSync( join( __dirname, 'fixtures', 'expected.txt' ) );

	createElement( setup(), done );

	function done( error, actual ) {
		if ( error ) {
			t.ok( false, error.message );
		} else {
			t.equal( actual+'\n', expected.toString(), 'returns expected value' );
		}
		t.end();
	}
});

tape( 'if not provided an option, the function will set a corresponding HTML attribute to either a default value (if one exists) or an empty string', function test( t ) {
	var expected = '
\n    <svg xmlns:xlink="http://www.w3.org/1999/xlink" width="0" height="0.343ex" style="vertical-align: -0.171ex;" viewBox="0 -73.8 0 147.5" role="img" focusable="false" xmlns="http://www.w3.org/2000/svg" aria-labelledby="MathJax-SVG-1-Title"><title id="MathJax-SVG-1-Title"></title><defs aria-hidden="true"></defs><g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)" aria-hidden="true"></g></svg>\n
';

	createElement( done );

	function done( error, actual ) {
		if ( error ) {
			t.ok( false, error.message );
		} else {
			t.equal( actual, expected.toString(), 'returns expected value' );
		}
		t.end();
	}
});

// TODO: add test for returning an error (e.g., when tex2svg fails (proxyquire))
<commit_msg>Fix broken test<commit_after>'use strict';

// MODULES //

var join = require( 'path' ).join;
var tape = require( 'tape' );
var noop = require( '@stdlib/utils/noop' );
var readFileSync = require( '@stdlib/fs/read-file' ).sync;
var createElement = require( './../lib' );

// FUNCTIONS //

function setup() {
	return {
		'className': 'equation',
		'align': 'center',
		'raw': 'y = mx + b',
		'label': 'eq:line'
	};
}

// TESTS //

tape( 'main export is a function', function test( t ) {
	t.equal( typeof createElement, 'function', 'main export is a function' );
	t.end();
});

tape( 'the function throws an error if provided an invalid `options` argument', function test( t ) {
	var values;
	var i;

	values = [
		'5',
		5,
		NaN,
		null,
		void 0,
		true,
		[],
		function noop() {}
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws when provided ' + values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			createElement( value, noop );
		};
	}
});

tape( 'the function throws an error if provided an invalid option', function test( t ) {
	var values;
	var i;

	values = [
		5,
		NaN,
		null,
		void 0,
		true,
		false,
		[],
		{},
		function noop() {}
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws when provided ' + values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			var opts = setup();
			opts.raw = value;
			createElement( opts, noop );
		};
	}
});

tape( 'the function throws an error if not provided a callback function (no options)', function test( t ) {
	var values;
	var i;

	values = [
		'5',
		5,
		NaN,
		null,
		void 0,
		true,
		false,
		[],
		{}
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws when provided ' + values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			createElement( value );
		};
	}
});

tape( 'the function throws an error if not provided a callback function (options)', function test( t ) {
	var values;
	var i;

	values = [
		'5',
		5,
		NaN,
		null,
		void 0,
		true,
		false,
		[],
		{}
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws when provided ' + values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			createElement( {}, value );
		};
	}
});

tape( 'the function returns an HTML string for inlining an SVG equation in Markdown', function test( t ) {
	var expected = readFileSync( join( __dirname, 'fixtures', 'expected.txt' ) );

	createElement( setup(), done );

	function done( error, actual ) {
		if ( error ) {
			t.ok( false, error.message );
		} else {
			t.equal( actual+'\n', expected.toString(), 'returns expected value' );
		}
		t.end();
	}
});

tape( 'if not provided an option, the function will set a corresponding HTML attribute to either a default value (if one exists) or an empty string', function test( t ) {
	var expected = '
\n    <svg xmlns:xlink="http://www.w3.org/1999/xlink" width="0" height="0.343ex" style="vertical-align: -0.171ex;" viewBox="0 -73.8 0 147.5" role="img" focusable="false" xmlns="http://www.w3.org/2000/svg" aria-labelledby="MathJax-SVG-1-Title">\n<title id="MathJax-SVG-1-Title"></title>\n<defs aria-hidden="true"></defs>\n<g stroke="currentColor" fill="currentColor" stroke-width="0" transform="matrix(1 0 0 -1 0 0)" aria-hidden="true"></g>\n</svg>\n
';

	createElement( done );

	function done( error, actual ) {
		if ( error ) {
			t.ok( false, error.message );
		} else {
			t.equal( actual, expected.toString(), 'returns expected value' );
		}
		t.end();
	}
});

// TODO: add test for returning an error (e.g., when tex2svg fails (proxyquire))
<|endoftext|>


<commit_before>Target = function(x, y) {
  this.x = x;
  this.y = y;
  this.life = 11;
  this.size = 12;

  return this;
}
Target.prototype.render = (function(context) {
  function render() {
    var x = this.x - gCamera.x;
    var y = this.y - gCamera.y;

    // Only render if within the camera's bounds
    if (gCamera.isInView(this)) {
      context.beginPath();
      context.arc(x + 2, y + 2, 13, 0, Math.PI * 2);
      context.fillStyle = '#222';
      context.fill();
      context.closePath();

      context.beginPath();
      context.arc(x, y, this.size, 0, Math.PI * 2);
      context.fillStyle = 'rgb(' + Math.round(255 * (this.life / this.size)) + ',' + Math.round(255 * ((this.size - this.life) / this.size)) + ',' + 0x22 + ')';
      context.fill();
      context.closePath();
    }
  }
  return render;
})(gRenderer.context);
<commit_msg>Update target.render to use global render functions<commit_after>Target = function(x, y) {
  this.x = x;
  this.y = y;
  this.life = 11;
  this.size = 12;

  return this;
}
Target.prototype.render = function() {
  var x = this.x - gCamera.x;
  var y = this.y - gCamera.y;

  // Only render if within the camera's bounds
  if (gCamera.isInView(this)) {
    renderPath([['arc', x + 2, y + 2, 13, 0, Math.PI * 2]]);
    fill('#222');

    renderPath([['arc', x, y, this.size, 0, Math.PI * 2]]);
    fill('rgb(' + Math.round(255 * (this.life / this.size)) + ',' + Math.round(255 * ((this.size - this.life) / this.size)) + ',' + 0x22 + ')');
  }
}
<|endoftext|>


<commit_before>/**
 * Primary gulpfile for running this application's tasks.
 *
 * The tasks listed here are for general use by developers and non-developers.
 */
'use strict';

const fs = require('fs-extra');
const gulp = require('gulp');
const requireDir = require('require-dir');
const runSequence = require('run-sequence');
const slash = require('slash');
const utils = require('fepper-utils');

const Fepper = require('./core/fepper');

// Set globals.
// Determine rootDir whether running headless or whether running a full implementation.
// global.appDir as set here might be temporary and be reset as the app_dir value from conf.yml.
const thisDir = global.appDir = slash(__dirname);
let rootDir = '';
let isHeaded = false;

if (process.env.HEADED) {
  isHeaded = true;
}

if (process.env.ROOT_DIR) {
  rootDir = slash(process.env.ROOT_DIR);

  if (!fs.existsSync(rootDir)) {
    rootDir = '';
  }
}
else {
  // utils.findup() will replace backslashes with slashes.
  rootDir = utils.findup('fepper.command', thisDir);

  if (rootDir) {
    isHeaded = true;
  }
}

// The only existing headless use-case is testing.
if (!isHeaded) {
  rootDir = `${thisDir}/test`;
}

if (!rootDir) {
  utils.error('It appears you are trying to run Fepper from a critically broken environment! Exiting!');

  return;
}

global.rootDir = rootDir;

utils.conf(isHeaded); // This resets global.appDir if conf.app_dir differs from it.
utils.pref(isHeaded);

if (!global.conf || !global.pref) {
  return;
}

// Instantiate a Fepper object and attach it to the global object.
global.fepper = new Fepper();

// Proceed with tasking.
const conf = global.conf;

// Require tasks in task directories.
requireDir('./tasker');

// Optionally require auxiliary, contrib, and custom tasks.
const extendDir = conf.extend_dir;
const auxDir = `${extendDir}/auxiliary`;
const conFile = `${extendDir}/contrib.js`;
const cusFile = `${extendDir}/custom.js`;
const auxExists = fs.existsSync(auxDir);
const conExists = fs.existsSync(conFile);
const cusExists = fs.existsSync(cusFile);

if (fs.existsSync(`${extendDir}/node_modules`)) {
  if (auxExists) {
    requireDir(auxDir);
  }

  if (conExists) {
    require(conFile);
  }

  if (cusExists) {
    require(cusFile);
  }

  // Search for extension tasks and require them.
  // Resorting to this long, rather unreadable block of code to obviate requiring the large Glob NPM.
  // (Yes, other dependencies also depend on Glob, so if Fepper were to stay in sync with at least one of them, there
  // wouldn't be any additional download overhead, but we don't want this bit of additional maintenance upkeep.)
  //
  // Require scripts ending in "~extend.js" at Level 1 and Level 2 below the "extend" directory.
  // Choosing for...of loops and their readability in exchange for performance.

  // Level 0 declarations.
  const dirsAtLevel0 = [];
  const level0 = extendDir;
  const basenamesAtLevel0 = fs.readdirSync(level0);
  const suffix = '~extend.js';

  for (let basenameAtLevel0 of basenamesAtLevel0) {
    try {
      const fileAtLevel0 = `${level0}/${basenameAtLevel0}`;
      const statAtLevel0 = fs.statSync(fileAtLevel0);

      if (statAtLevel0.isDirectory()) {
        dirsAtLevel0.push(fileAtLevel0);
      }
    }
    catch (err) {
      utils.error(err);
    }
  }

  for (let dirAtLevel0 of dirsAtLevel0) {
    // Level 1 declarations.
    const dirsAtLevel1 = [];
    const basenamesAtLevel1 = fs.readdirSync(dirAtLevel0);

    for (let basenameAtLevel1 of basenamesAtLevel1) {
      try {
        const fileAtLevel1 = `${dirAtLevel0}/${basenameAtLevel1}`;
        const statAtLevel1 = fs.statSync(fileAtLevel1);

        if (statAtLevel1.isFile() && fileAtLevel1.indexOf(suffix) === fileAtLevel1.length - suffix.length) {
          require(fileAtLevel1);
        }
        else if (statAtLevel1.isDirectory()) {
          dirsAtLevel1.push(fileAtLevel1);
        }
      }
      catch (err) {
        utils.error(err);
      }
    }

    for (let dirAtLevel1 of dirsAtLevel1) {
      // Level 2 declarations.
      const basenamesAtLevel2 = fs.readdirSync(dirAtLevel1);

      for (let basenameAtLevel2 of basenamesAtLevel2) {
        try {
          const fileAtLevel2 = `${dirAtLevel1}/${basenameAtLevel2}`;
          const statAtLevel2 = fs.statSync(fileAtLevel2);

          if (statAtLevel2.isFile() && fileAtLevel2.indexOf(suffix) === fileAtLevel2.length - suffix.length) {
            require(fileAtLevel2);
          }
        }
        catch (err) {
          utils.error(err);
        }
      }
    }
  }
}

// Main tasks.
gulp.task('default', cb => {
  let args = [];

  args.push('once');
  args.push('tcp-ip-load:init');

  if (conExists && cusExists) {

    // TCP-IP overrides must run after tcp-ip-load:init in order for there to be a global.expressApp object to override.
    // They must then override it before it starts listening and tcp-ip-reload starts watching.
    args.push(['contrib:tcp-ip', 'custom:tcp-ip']);
  }

  args.push(['tcp-ip-load:listen', 'tcp-ip-reload:listen']);

  if (conExists && cusExists) {
    args.push(['contrib:watch', 'custom:watch', 'tcp-ip-load:open', 'tcp-ip-reload:watch']);

    // Probably no use-case for these contrib and custom postprocess tasks, but here just in case.
    args.push(['contrib:tcp-ip:postprocess', 'custom:tcp-ip:postprocess']);
  }
  else {
    args.push(['tcp-ip-load:open', 'tcp-ip-reload:watch']);
  }

  args.push(() => {
    cb();
    utils.log(`Listening on port ${conf.express_port}`);
  });

  runSequence.apply(null, args);
});

gulp.task('data', cb => {
  let args = [];

  if (conExists && cusExists) {
    args.push(['contrib:data', 'custom:data']);
  }

  args.push('fepper:data');

  if (conExists && cusExists) {
    args.push(['contrib:data:postprocess', 'custom:data:postprocess']);
  }

  args.push('ui:build');

  if (conf.ui.cleanPublic) {
    args.push('ui:copy');
    args.push('ui:copy-styles');
  }

  args.push(cb);

  runSequence.apply(null, args);
});

gulp.task('frontend-copy', cb => {
  let args = [];

  if (conExists && cusExists) {
    args.push(['contrib:frontend-copy', 'custom:frontend-copy']);
  }

  args.push(['fepper:copy-assets', 'fepper:copy-scripts', 'fepper:copy-styles']);

  if (conExists && cusExists) {
    args.push(['contrib:frontend-copy:postprocess', 'custom:frontend-copy:postprocess']);
  }

  args.push(cb);

  runSequence.apply(null, args);
});

gulp.task('install', cb => {
  runSequence(
    'install:copy',
    cb
  );
});

gulp.task('once', cb => {
  let args = [];

  if (conExists && cusExists) {
    args.push(['contrib:once', 'custom:once']);
    args.push(['contrib:data', 'custom:data']);
  }

  args.push('fepper:data');

  if (conExists && cusExists) {
    args.push(['contrib:data:postprocess', 'custom:data:postprocess']);
  }

  args.push('ui:clean');
  args.push('ui:build');
  args.push('ui:copy');
  args.push('ui:copy-styles');

  if (conExists && cusExists) {
    args.push(['contrib:once:postprocess', 'custom:once:postprocess']);
  }

  args.push(cb);

  runSequence.apply(null, args);
});

gulp.task('restart', cb => {
  let args = [];

  args.push('once');
  args.push('tcp-ip-load:init');

  if (conExists && cusExists) {

    // TCP-IP overrides must run after tcp-ip-load:init in order for there to be a global.expressApp object to override.
    // They must then override it before it starts listening and tcp-ip-reload starts watching.
    args.push(['contrib:tcp-ip', 'custom:tcp-ip']);
  }

  args.push(['tcp-ip-load:listen', 'tcp-ip-reload:listen']);

  if (conExists && cusExists) {
    args.push(['contrib:watch', 'custom:watch', 'tcp-ip-reload:watch']);

    // Probably no use-case for these contrib and custom postprocess tasks, but here just in case.
    args.push(['contrib:tcp-ip:postprocess', 'custom:tcp-ip:postprocess']);
  }
  else {
    args.push('tcp-ip-reload:watch');
  }

  args.push(() => {
    cb();
    utils.log(`Listening on port ${conf.express_port}`);
  });

  // An added measure for power usage, delete any lingering install.log, normally deleted by the plain `fp` task.
  const log = `${rootDir}/install.log`;

  if (fs.existsSync(log)) {
    fs.unlinkSync(log);
  }

  runSequence.apply(null, args);
});

gulp.task('static', cb => {
  let args = [];

  if (conExists && cusExists) {
    args.push(['contrib:static', 'custom:static']);
  }

  args.push('once');
  args.push('fepper:static-generate');

  if (conExists && cusExists) {
    args.push(['contrib:static:postprocess', 'custom:static:postprocess']);
  }

  args.push(cb);

  runSequence.apply(null, args);
});

gulp.task('syncback', cb => {
  let args = [];

  if (conExists && cusExists) {
    args.push(['contrib:syncback', 'custom:syncback']);
  }

  args.push('frontend-copy');
  args.push('template');

  if (conExists && cusExists) {
    args.push(['contrib:syncback:postprocess', 'custom:syncback:postprocess']);
  }

  args.push(cb);

  runSequence.apply(null, args);
});

gulp.task('template', cb => {
  let args = [];

  if (conExists && cusExists) {
    args.push(['contrib:template', 'custom:template']);
  }

  args.push('fepper:template');

  if (conExists && cusExists) {
    args.push(['contrib:template:postprocess', 'custom:template:postprocess']);
  }

  args.push(cb);

  runSequence.apply(null, args);
});

gulp.task('test', cb => {
  runSequence(
    'test:eslint',
    'test:mocha',
    cb
  );
});
<commit_msg>stronger logic for extension tasks<commit_after>/**
 * Primary gulpfile for running this application's tasks.
 *
 * The tasks listed here are for general use by developers and non-developers.
 */
'use strict';

const fs = require('fs-extra');
const gulp = require('gulp');
const requireDir = require('require-dir');
const runSequence = require('run-sequence');
const slash = require('slash');
const utils = require('fepper-utils');

const Fepper = require('./core/fepper');

// Set globals.
// Determine rootDir whether running headless or whether running a full implementation.
// global.appDir as set here might be temporary and be reset as the app_dir value from conf.yml.
const thisDir = global.appDir = slash(__dirname);
let rootDir = '';
let isHeaded = false;

if (process.env.HEADED) {
  isHeaded = true;
}

if (process.env.ROOT_DIR) {
  rootDir = slash(process.env.ROOT_DIR);

  if (!fs.existsSync(rootDir)) {
    rootDir = '';
  }
}
else {
  // utils.findup() will replace backslashes with slashes.
  rootDir = utils.findup('fepper.command', thisDir);

  if (rootDir) {
    isHeaded = true;
  }
}

// The only existing headless use-case is testing.
if (!isHeaded) {
  rootDir = `${thisDir}/test`;
}

if (!rootDir) {
  utils.error('It appears you are trying to run Fepper from a critically broken environment! Exiting!');

  return;
}

global.rootDir = rootDir;

utils.conf(isHeaded); // This resets global.appDir if conf.app_dir differs from it.
utils.pref(isHeaded);

if (!global.conf || !global.pref) {
  return;
}

// Instantiate a Fepper object and attach it to the global object.
global.fepper = new Fepper();

// Proceed with tasking.
const conf = global.conf;

// Require tasks in task directories.
requireDir('./tasker');

// Optionally require auxiliary, contrib, and custom tasks.
const extendDir = conf.extend_dir;
const auxConFile = `${extendDir}/auxiliary/auxiliary-contrib.js`;
const auxCusFile = `${extendDir}/auxiliary/auxiliary-custom.js`;
const conFile = `${extendDir}/contrib.js`;
const cusFile = `${extendDir}/custom.js`;
const auxConExists = fs.existsSync(auxConFile);
const auxCusExists = fs.existsSync(auxCusFile);
const conExists = fs.existsSync(conFile);
const cusExists = fs.existsSync(cusFile);

if (auxConExists) {
  require(auxConFile);
}

if (auxCusExists) {
  require(auxCusFile);
}

if (conExists) {
  require(conFile);
}

if (cusExists) {
  require(cusFile);
}

// Search for extension tasks and require them.
// Resorting to this long, rather unreadable block of code to obviate requiring the large Glob NPM.
// (Yes, other dependencies also depend on Glob, so if Fepper were to stay in sync with at least one of them, there
// wouldn't be any additional download overhead, but we don't want this bit of additional maintenance upkeep.)
//
// Require scripts ending in "~extend.js" at Level 1 and Level 2 below the "extend" directory.
// Choosing for...of loops and their readability in exchange for performance.

// Level 0 declarations.
const dirsAtLevel0 = [];
const level0 = extendDir;
const basenamesAtLevel0 = fs.readdirSync(level0);
const suffix = '~extend.js';

for (let basenameAtLevel0 of basenamesAtLevel0) {
  try {
    const fileAtLevel0 = `${level0}/${basenameAtLevel0}`;
    const statAtLevel0 = fs.statSync(fileAtLevel0);

    if (statAtLevel0.isDirectory()) {
      dirsAtLevel0.push(fileAtLevel0);
    }
  }
  catch (err) {
    utils.error(err);
  }
}

for (let dirAtLevel0 of dirsAtLevel0) {
  // Level 1 declarations.
  const dirsAtLevel1 = [];
  const basenamesAtLevel1 = fs.readdirSync(dirAtLevel0);

  for (let basenameAtLevel1 of basenamesAtLevel1) {
    try {
      const fileAtLevel1 = `${dirAtLevel0}/${basenameAtLevel1}`;
      const statAtLevel1 = fs.statSync(fileAtLevel1);

      if (statAtLevel1.isFile() && fileAtLevel1.indexOf(suffix) === fileAtLevel1.length - suffix.length) {
        require(fileAtLevel1);
      }
      else if (statAtLevel1.isDirectory()) {
        dirsAtLevel1.push(fileAtLevel1);
      }
    }
    catch (err) {
      utils.error(err);
    }
  }

  for (let dirAtLevel1 of dirsAtLevel1) {
    // Level 2 declarations.
    const basenamesAtLevel2 = fs.readdirSync(dirAtLevel1);

    for (let basenameAtLevel2 of basenamesAtLevel2) {
      try {
        const fileAtLevel2 = `${dirAtLevel1}/${basenameAtLevel2}`;
        const statAtLevel2 = fs.statSync(fileAtLevel2);

        if (statAtLevel2.isFile() && fileAtLevel2.indexOf(suffix) === fileAtLevel2.length - suffix.length) {
          require(fileAtLevel2);
        }
      }
      catch (err) {
        utils.error(err);
      }
    }
  }
}

function extensionsPush(taskName, argsArr, tasksArr = []) {
  let isAuxiliary = false;

  if (taskName.slice(-12) === ':postprocess') {
    isAuxiliary = true;
  }

  if (isAuxiliary) {
    if (auxConExists) {
      tasksArr.push(`contrib:${taskName}`);
    }

    if (auxCusExists) {
      tasksArr.push(`custom:${taskName}`);
    }
  }
  else {
    if (conExists) {
      tasksArr.push(`contrib:${taskName}`);
    }

    if (cusExists) {
      tasksArr.push(`custom:${taskName}`);
    }
  }

  if (tasksArr.length) {
    argsArr.push(tasksArr);
  }
}

// Main tasks.
gulp.task('default', (cb) => {
  const args = [];

  args.push('once');
  args.push('tcp-ip-load:init');

  // TCP-IP overrides must run after tcp-ip-load:init in order for there to be a global.expressApp object to override.
  // They must run before global.expressApp starts listening and tcp-ip-reload starts watching.
  extensionsPush('tcp-ip', args);
  args.push(['tcp-ip-load:listen', 'tcp-ip-reload:listen']);

  const tasks = ['tcp-ip-load:open', 'tcp-ip-reload:watch'];

  extensionsPush('watch', args, tasks);

  // Probably no use-case for these tcp-ip:postprocess tasks, but here just in case.
  extensionsPush('tcp-ip:postprocess', args);

  args.push(() => {
    cb();
    utils.log(`Listening on port ${conf.express_port}`);
  });
  runSequence.apply(null, args);
});

gulp.task('data', (cb) => {
  const args = [];

  extensionsPush('data', args);
  args.push('fepper:data');
  extensionsPush('data:postprocess', args);
  args.push('ui:build');

  if (conf.ui.cleanPublic) {
    args.push('ui:copy');
    args.push('ui:copy-styles');
  }

  args.push(cb);
  runSequence.apply(null, args);
});

gulp.task('frontend-copy', (cb) => {
  const args = [];

  extensionsPush('frontend-copy', args);
  args.push(['fepper:copy-assets', 'fepper:copy-scripts', 'fepper:copy-styles']);
  extensionsPush('frontend-copy:postprocess', args);
  args.push(cb);
  runSequence.apply(null, args);
});

gulp.task('install', (cb) => {
  runSequence(
    'install:copy',
    cb
  );
});

gulp.task('once', (cb) => {
  const args = [];

  extensionsPush('once', args);

  // Data tasks grouped as follows. "once" extension tasks run before data tasks.
  // "ui" tasks and "once" postprocess tasks run after.
  extensionsPush('data', args);
  args.push('fepper:data');
  extensionsPush('data:postprocess', args);

  args.push('ui:clean');
  args.push('ui:build');
  args.push('ui:copy');
  args.push('ui:copy-styles');

  extensionsPush('once:postprocess', args);
  args.push(cb);
  runSequence.apply(null, args);
});

gulp.task('restart', (cb) => {
  const args = [];

  args.push('once');
  args.push('tcp-ip-load:init');

  // TCP-IP overrides must run after tcp-ip-load:init in order for there to be a global.expressApp object to override.
  // They must run before global.expressApp starts listening and tcp-ip-reload starts watching.
  extensionsPush('tcp-ip', args);
  args.push(['tcp-ip-load:listen', 'tcp-ip-reload:listen']);

  const tasks = ['tcp-ip-reload:watch'];

  extensionsPush('watch', args, tasks);

  // Probably no use-case for these tcp-ip:postprocess tasks, but here just in case.
  extensionsPush('tcp-ip:postprocess', args);

  args.push(() => {
    cb();
    utils.log(`Listening on port ${conf.express_port}`);
  });

  // An added measure for power usage, delete any lingering install.log, normally deleted by the plain `fp` task.
  const log = `${rootDir}/install.log`;

  if (fs.existsSync(log)) {
    fs.unlinkSync(log);
  }

  runSequence.apply(null, args);
});

gulp.task('static', (cb) => {
  const args = [];

  extensionsPush('static', args);
  args.push('once');
  args.push('fepper:static-generate');
  extensionsPush('static:postprocess', args);
  args.push(cb);
  runSequence.apply(null, args);
});

gulp.task('syncback', (cb) => {
  const args = [];

  extensionsPush('syncback', args);
  args.push('frontend-copy');
  args.push('template');
  extensionsPush('syncback:postprocess', args);
  args.push(cb);
  runSequence.apply(null, args);
});

gulp.task('template', (cb) => {
  const args = [];

  extensionsPush('template', args);
  args.push('fepper:template');
  extensionsPush('template:postprocess', args);
  args.push(cb);
  runSequence.apply(null, args);
});

gulp.task('test', (cb) => {
  runSequence(
    'test:eslint',
    'test:mocha',
    cb
  );
});
<|endoftext|>


<commit_before>/**
 * All reading related code here. This is so that we can separate the async code from sync code
 * for testability
 */
require.paths.push(__dirname);
var fs       = require('fs'),
    callback = require('callback');

var NEW_LINE = /\n\r?/;

function collect(callback){
  findJsFiles('src', callback.waitMany(function(file) {
    //console.log('reading', file, '...');
    findNgDocInJsFile(file, callback.waitMany(function(doc, line) {
      callback(doc, file, line);
    }));
  }));
  findNgDocInDir('docs/', callback.waitMany(callback));
  callback.done();
}

function findJsFiles(dir, callback){
  fs.readdir(dir, callback.waitFor(function(err, files){
    if (err) return this.error(err);
    files.forEach(function(file){
      var path = dir + '/' + file;
      fs.lstat(path, callback.waitFor(function(err, stat){
        if (err) return this.error(err);
        if (stat.isDirectory())
          findJsFiles(path, callback.waitMany(callback));
        else if (/\.js$/.test(path))
          callback(path);
      }));
    });
    callback.done();
  }));
}

function findNgDocInDir(directory, docNotify) {
  fs.readdir(directory, docNotify.waitFor(function(err, files){
    if (err) return this.error(err);
    files.forEach(function(file){
      //console.log('reading', directory + file, '...');
      if (!file.match(/\.ngdoc$/)) return;
      fs.readFile(directory + file, docNotify.waitFor(function(err, content){
        if (err) return this.error(err);
        docNotify(content.toString(), directory + file, 1);
      }));
    });
    docNotify.done();
  }));
}

function findNgDocInJsFile(file, callback) {
  fs.readFile(file, callback.waitFor(function(err, content){
    var lines = content.toString().split(NEW_LINE);
    var text;
    var startingLine ;
    var match;
    var inDoc = false;
    lines.forEach(function(line, lineNumber){
      lineNumber++;
      // is the comment starting?
      if (!inDoc && (match = line.match(/^\s*\/\*\*\s*(.*)$/))) {
        line = match[1];
        inDoc = true;
        text = [];
        startingLine = lineNumber;
      }
      // are we done?
      if (inDoc && line.match(/\*\//)) {
        text = text.join('\n');
        text = text.replace(/^\n/, '');
        if (text.match(/@ngdoc/)){
          callback(text, startingLine);
        }
        doc = null;
        inDoc = false;
      }
      // is the comment add text
      if (inDoc){
        text.push(line.replace(/^\s*\*\s?/, ''));
      }
    });
    callback.done();
  }));
}

exports.collect = collect;
<commit_msg>process only tutorial files<commit_after>/**
 * All reading related code here. This is so that we can separate the async code from sync code
 * for testability
 */
require.paths.push(__dirname);
var fs       = require('fs'),
    callback = require('callback');

var NEW_LINE = /\n\r?/;

function collect(callback){
/*
   findJsFiles('src', callback.waitMany(function(file) {
     //console.log('reading', file, '...');
     findNgDocInJsFile(file, callback.waitMany(function(doc, line) {
       callback(doc, file, line);
    }));
  }));
*/
  findNgDocInDir('docs/', callback.waitMany(callback));
  callback.done();
}

function findJsFiles(dir, callback){
  fs.readdir(dir, callback.waitFor(function(err, files){
    if (err) return this.error(err);
    files.forEach(function(file){
      var path = dir + '/' + file;
      fs.lstat(path, callback.waitFor(function(err, stat){
        if (err) return this.error(err);
        if (stat.isDirectory())
          findJsFiles(path, callback.waitMany(callback));
        else if (/\.js$/.test(path))
          callback(path);
      }));
    });
    callback.done();
  }));
}

function findNgDocInDir(directory, docNotify) {
  fs.readdir(directory, docNotify.waitFor(function(err, files){
    if (err) return this.error(err);
    files.forEach(function(file){
      //console.log('reading', directory + file, '...');
      if (!file.match(/tutorial.*\.ngdoc$/)) return;
      fs.readFile(directory + file, docNotify.waitFor(function(err, content){
        if (err) return this.error(err);
        docNotify(content.toString(), directory + file, 1);
      }));
    });
    docNotify.done();
  }));
}

function findNgDocInJsFile(file, callback) {
  fs.readFile(file, callback.waitFor(function(err, content){
    var lines = content.toString().split(NEW_LINE);
    var text;
    var startingLine ;
    var match;
    var inDoc = false;
    lines.forEach(function(line, lineNumber){
      lineNumber++;
      // is the comment starting?
      if (!inDoc && (match = line.match(/^\s*\/\*\*\s*(.*)$/))) {
        line = match[1];
        inDoc = true;
        text = [];
        startingLine = lineNumber;
      }
      // are we done?
      if (inDoc && line.match(/\*\//)) {
        text = text.join('\n');
        text = text.replace(/^\n/, '');
        if (text.match(/@ngdoc/)){
          callback(text, startingLine);
        }
        doc = null;
        inDoc = false;
      }
      // is the comment add text
      if (inDoc){
        text.push(line.replace(/^\s*\*\s?/, ''));
      }
    });
    callback.done();
  }));
}

exports.collect = collect;
<|endoftext|>