<commit_before>import React, { Component, PropTypes } from 'react';
import ol from 'openlayers';
import AutoComplete from 'material-ui/AutoComplete';
import Slider from 'material-ui/Slider';
import RaisedButton from 'material-ui/RaisedButton';
import FontIcon from 'material-ui/FontIcon';
import SelectField from 'material-ui/SelectField';
import MenuItem from 'material-ui/MenuItem';
import TextField from 'material-ui/TextField';
import { green700 } from 'material-ui/styles/colors';
import config from '../config';

const styles = {
  menu: {
    margin: '10px 20px 30px'
  },

  reachabilitySlider: {
    marginBottom: '0px'
  },

  batteryLevel: {
    display: 'flex',
    justifyContent: 'space-between'
  },

  batteryLevelValue: {
    fontWeight: 'bold',
    color: green700,
    fontSize: '14px'
  },

  autoCompleteWrapper: {
    position: 'relative',
    display: 'flex'
  },

  rangeTextField: {
    display: 'inherit',
    position: 'relative',
    marginBottom: '25px'
  },

  buttonDiv: {
    display: 'flex',
  },

  displayButton: {
    marginRight: '18px'
  }
};

export default class ReachabilityTab extends Component {
  constructor(props) {
    super(props);
    this.state = {
      dataSource: [],
    };

    window.google.load('maps', '3', {
      other_params: `key=${config.GOOGLE_MAP_KEY}&libraries=places`
    });
    window.google.setOnLoadCallback(this.initialize);
  }

  getCoordinateFromPlaceId = id => new Promise((resolve) => {
    this.state.placesService.getDetails({ placeId: id }, (results, status) => {
      if (status === window.google.maps.places.PlacesServiceStatus.OK) {
        resolve([results.geometry.location.lng(), results.geometry.location.lat()]);
      }
    });
  })

  initialize = () => {
    const map = new window.google.maps.Map(document.getElementById('gmap'));
    this.setState({
      autocompleteService: new window.google.maps.places.AutocompleteService(),
      placesService: new window.google.maps.places.PlacesService(map),
    });
  }

  handleToRequest = (chosenRequest) => {
    this.getCoordinateFromPlaceId(chosenRequest.value).then((coord) => {
      this.props.setRangePolygonDestination(ol.proj.transform(coord, 'EPSG:4326', 'EPSG:3857'));
    });
  }

  handleFromRequest = (chosenRequest) => {
    this.getCoordinateFromPlaceId(chosenRequest.value).then((coord) => {
      this.props.setRangePolygonOrigin(ol.proj.transform(coord, 'EPSG:4326', 'EPSG:3857'));
    });
  }

  updateFromInput = (value) => {
    this.props.updateRangeFromField(value);
    if (value.length > 0) {
      this.updateAutocomplete(value);
    }
  };

  updateToInput = (value) => {
    this.props.updateRangeToField(value);
    if (value.length > 0) {
      this.updateAutocomplete(value);
    }
  };

  updateAutocomplete = (value) => {
    this.state.autocompleteService.getQueryPredictions({ input: value }, (predictions, status) => {
      if (status === window.google.maps.places.PlacesServiceStatus.OK) {
        const results = [];
        predictions.forEach((prediction) => {
          if (prediction.description && prediction.place_id) {
            results.push({
              text: prediction.description,
              value: prediction.place_id,
            });
          }
        });
        this.setState({ dataSource: results });
      }
      else {
        this.setState({ dataSource: [] });
      }
    });
  };

  render() {
    return (

          <AutoComplete
            searchText={this.props.rangeFromField}
            floatingLabelText="From"
            onClick={() => this.props.updateRangeFromSelected(true)}
            onNewRequest={this.handleFromRequest}
            onUpdateInput={this.updateFromInput}
            dataSource={this.state.dataSource}
            filter={AutoComplete.noFilter}
            fullWidth
          />

          <AutoComplete
            searchText={this.props.rangeToField}
            floatingLabelText="To"
            onClick={() => this.props.updateRangeToSelected(true)}
            onNewRequest={this.handleToRequest}
            onUpdateInput={this.updateToInput}
            dataSource={this.state.dataSource}
            filter={AutoComplete.noFilter}
            fullWidth
          />

        <SelectField
          floatingLabelText="Vehicle"
          value={this.props.vehicle}
          onChange={this.props.vehicleChange}
          maxHeight={210}
          fullWidth
        >
          {this.props.getVehicles().map((vehicle, index) => (
            <MenuItem key={vehicle} value={index} primaryText={vehicle} />
          ))}
        </SelectField>

          Battery Level
           (this.batteryLevel = node)}
          >
            {`${this.props.batteryPecentage}%`}

        <Slider
          onChange={this.props.updateBatterySlider}
          value={this.props.batteryLevel}
          sliderStyle={styles.reachabilitySlider}
        />
        <TextField
          onChange={this.props.updateRemainingRange}
          style={styles.rangeTextField}
          floatingLabelText="Remaining Range"
          value={Math.round(this.props.remainingRange * 100) / 100 || ''}
        />

          <RaisedButton
            label="Display"
            onClick={this.props.getRangeVisualisation}
            icon={<FontIcon className="material-icons">map</FontIcon>}
            style={styles.displayButton}
          />
          {this.props.rangePolygonVisible ?
            <RaisedButton
              label="Hide"
              onClick={this.props.hideRangeVisualisation}
              icon={<FontIcon className="material-icons">map</FontIcon>}
            /> : null}

    );
  }
}

ReachabilityTab.propTypes = {
  vehicle: PropTypes.number.isRequired,
  batteryLevel: PropTypes.number.isRequired,
  batteryPecentage: PropTypes.number.isRequired,
  updateBatterySlider: PropTypes.func.isRequired,
  rangePolygonVisible: PropTypes.bool.isRequired,
  remainingRange: PropTypes.number.isRequired,
  updateRemainingRange: PropTypes.func.isRequired,
  getVehicles: PropTypes.func.isRequired,
  vehicleChange: PropTypes.func.isRequired,
  getRangeVisualisation: PropTypes.func.isRequired,
  hideRangeVisualisation: PropTypes.func.isRequired,
  rangeFromField: PropTypes.string.isRequired,
  updateRangeFromField: PropTypes.func.isRequired,
  updateRangeFromSelected: PropTypes.func.isRequired,
  rangeToField: PropTypes.string.isRequired,
  updateRangeToField: PropTypes.func.isRequired,
  updateRangeToSelected: PropTypes.func.isRequired,
  setRangePolygonOrigin: PropTypes.func.isRequired,
  setRangePolygonDestination: PropTypes.func.isRequired,
};
<commit_msg>Fix AutoComplete: Uncaught (in promise) Error: Missing parameter. You must specify placeId.<commit_after>import React, { Component, PropTypes } from 'react';
import ol from 'openlayers';
import AutoComplete from 'material-ui/AutoComplete';
import Slider from 'material-ui/Slider';
import RaisedButton from 'material-ui/RaisedButton';
import FontIcon from 'material-ui/FontIcon';
import SelectField from 'material-ui/SelectField';
import MenuItem from 'material-ui/MenuItem';
import TextField from 'material-ui/TextField';
import { green700 } from 'material-ui/styles/colors';
import config from '../config';

const styles = {
  menu: {
    margin: '10px 20px 30px'
  },

  reachabilitySlider: {
    marginBottom: '0px'
  },

  batteryLevel: {
    display: 'flex',
    justifyContent: 'space-between'
  },

  batteryLevelValue: {
    fontWeight: 'bold',
    color: green700,
    fontSize: '14px'
  },

  autoCompleteWrapper: {
    position: 'relative',
    display: 'flex'
  },

  rangeTextField: {
    display: 'inherit',
    position: 'relative',
    marginBottom: '25px'
  },

  buttonDiv: {
    display: 'flex',
  },

  displayButton: {
    marginRight: '18px'
  }
};

export default class ReachabilityTab extends Component {
  constructor(props) {
    super(props);
    this.state = {
      dataSource: [],
    };

    window.google.load('maps', '3', {
      other_params: `key=${config.GOOGLE_MAP_KEY}&libraries=places`
    });
    window.google.setOnLoadCallback(this.initialize);
  }

  getCoordinateFromPlaceId = id => new Promise((resolve) => {
    this.state.placesService.getDetails({ placeId: id }, (results, status) => {
      if (status === window.google.maps.places.PlacesServiceStatus.OK) {
        resolve([results.geometry.location.lng(), results.geometry.location.lat()]);
      }
    });
  })

  initialize = () => {
    const map = new window.google.maps.Map(document.getElementById('gmap'));
    this.setState({
      autocompleteService: new window.google.maps.places.AutocompleteService(),
      placesService: new window.google.maps.places.PlacesService(map),
    });
  }

  handleToRequest = (chosenRequest) => {
    if (chosenRequest.value) {
      this.getCoordinateFromPlaceId(chosenRequest.value).then((coord) => {
        this.props.setRangePolygonDestination(ol.proj.transform(coord, 'EPSG:4326', 'EPSG:3857'));
      });
    }
  }

  handleFromRequest = (chosenRequest) => {
    if (chosenRequest.value) {
      this.getCoordinateFromPlaceId(chosenRequest.value).then((coord) => {
        this.props.setRangePolygonOrigin(ol.proj.transform(coord, 'EPSG:4326', 'EPSG:3857'));
      });
    }
  }

  updateFromInput = (value) => {
    this.props.updateRangeFromField(value);
    if (value.length > 0) {
      this.updateAutocomplete(value);
    }
  };

  updateToInput = (value) => {
    this.props.updateRangeToField(value);
    if (value.length > 0) {
      this.updateAutocomplete(value);
    }
  };

  updateAutocomplete = (value) => {
    this.state.autocompleteService.getQueryPredictions({ input: value }, (predictions, status) => {
      if (status === window.google.maps.places.PlacesServiceStatus.OK) {
        const results = [];
        predictions.forEach((prediction) => {
          if (prediction.description && prediction.place_id) {
            results.push({
              text: prediction.description,
              value: prediction.place_id,
            });
          }
        });
        this.setState({ dataSource: results });
      }
      else {
        this.setState({ dataSource: [] });
      }
    });
  };

  render() {
    return (

          <AutoComplete
            searchText={this.props.rangeFromField}
            floatingLabelText="From"
            onClick={() => this.props.updateRangeFromSelected(true)}
            onNewRequest={this.handleFromRequest}
            onUpdateInput={this.updateFromInput}
            dataSource={this.state.dataSource}
            filter={AutoComplete.noFilter}
            fullWidth
          />

          <AutoComplete
            searchText={this.props.rangeToField}
            floatingLabelText="To"
            onClick={() => this.props.updateRangeToSelected(true)}
            onNewRequest={this.handleToRequest}
            onUpdateInput={this.updateToInput}
            dataSource={this.state.dataSource}
            filter={AutoComplete.noFilter}
            fullWidth
          />

        <SelectField
          floatingLabelText="Vehicle"
          value={this.props.vehicle}
          onChange={this.props.vehicleChange}
          maxHeight={210}
          fullWidth
        >
          {this.props.getVehicles().map((vehicle, index) => (
            <MenuItem key={vehicle} value={index} primaryText={vehicle} />
          ))}
        </SelectField>

          Battery Level
           (this.batteryLevel = node)}
          >
            {`${this.props.batteryPecentage}%`}

        <Slider
          onChange={this.props.updateBatterySlider}
          value={this.props.batteryLevel}
          sliderStyle={styles.reachabilitySlider}
        />
        <TextField
          onChange={this.props.updateRemainingRange}
          style={styles.rangeTextField}
          floatingLabelText="Remaining Range"
          value={Math.round(this.props.remainingRange * 100) / 100 || ''}
        />

          <RaisedButton
            label="Display"
            onClick={this.props.getRangeVisualisation}
            icon={<FontIcon className="material-icons">map</FontIcon>}
            style={styles.displayButton}
          />
          {this.props.rangePolygonVisible ?
            <RaisedButton
              label="Hide"
              onClick={this.props.hideRangeVisualisation}
              icon={<FontIcon className="material-icons">map</FontIcon>}
            /> : null}

    );
  }
}

ReachabilityTab.propTypes = {
  vehicle: PropTypes.number.isRequired,
  batteryLevel: PropTypes.number.isRequired,
  batteryPecentage: PropTypes.number.isRequired,
  updateBatterySlider: PropTypes.func.isRequired,
  rangePolygonVisible: PropTypes.bool.isRequired,
  remainingRange: PropTypes.number.isRequired,
  updateRemainingRange: PropTypes.func.isRequired,
  getVehicles: PropTypes.func.isRequired,
  vehicleChange: PropTypes.func.isRequired,
  getRangeVisualisation: PropTypes.func.isRequired,
  hideRangeVisualisation: PropTypes.func.isRequired,
  rangeFromField: PropTypes.string.isRequired,
  updateRangeFromField: PropTypes.func.isRequired,
  updateRangeFromSelected: PropTypes.func.isRequired,
  rangeToField: PropTypes.string.isRequired,
  updateRangeToField: PropTypes.func.isRequired,
  updateRangeToSelected: PropTypes.func.isRequired,
  setRangePolygonOrigin: PropTypes.func.isRequired,
  setRangePolygonDestination: PropTypes.func.isRequired,
};
<|endoftext|>


<commit_before>'use strict'

const MetaRole = require('roles_meta')
const CONTROLLER_MESSAGE = '* Self Managed Code * quorum.tedivm.com * #quorum in Slack *'

class Spook extends MetaRole {
  getBuild (room, options) {
    return [MOVE]
  }

  manageCreep (creep) {
    // Delete current target if it is currently visible.
    if (creep.memory.starget && Game.rooms[creep.memory.starget]) {
      delete creep.memory.starget
    }

    // Harass current room by signing controller and stomping contruction sites.
    if (!creep.room.controller || !creep.room.controller.my) {
      if (!creep.memory.stomproom || creep.memory.stomproom !== creep.room.name) {
        creep.memory.stomproom = creep.room.name
        creep.memory.stomptime = Game.time
      }

      if (Game.time - creep.memory.stomptime < 70) {
        // Find and destroy any hostile construction sites
        if (this.stompConstruction(creep)) {
          return
        }
        // Tag the controller
        if (this.signController(creep)) {
          return
        }
      }
    }

    // Move on to the next room
    this.migrateRooms(creep)
  }

  stompConstruction (creep) {
    // Use cached construction site
    if (creep.memory.stomp) {
      let construction = Game.getObjectById(creep.memory.stomp)
      if (construction) {
        creep.travelTo(construction)
        return true
      } else {
        delete creep.memory.stomp
      }
    }
    // Find a new site to stomp, excluding any being stood on.
    const construction = creep.pos.findClosestByRange(FIND_HOSTILE_CONSTRUCTION_SITES, {filter: function (site) {
      return site.pos.getRangeTo(creep) > 0
    }})
    if (!construction) {
      return false
    }
    creep.memory.stomp = construction.id
    creep.travelTo(construction)
    return true
  }

  signController (creep) {
    if (!creep.room.controller) {
      return false
    }
    if (creep.room.controller.sign && creep.room.controller.sign.text === CONTROLLER_MESSAGE) {
      return false
    }
    if (creep.pos.isNearTo(creep.room.controller)) {
      creep.signController(creep.room.controller, CONTROLLER_MESSAGE)
    } else {
      creep.travelTo(creep.room.controller)
    }
    return true
  }

  migrateRooms (creep) {
    let target
    if (creep.memory.starget && creep.memory.starget !== creep.room.name) {
      target = creep.memory.starget
    } else {
      target = Room.getScoutTarget(creep)
    }
    creep.travelTo(new RoomPosition(25, 25, target), {range: 23})
  }
}

module.exports = Spook
<commit_msg>Disable attack notifications for spook<commit_after>'use strict'

const MetaRole = require('roles_meta')
const CONTROLLER_MESSAGE = '* Self Managed Code * quorum.tedivm.com * #quorum in Slack *'

class Spook extends MetaRole {
  getBuild (room, options) {
    return [MOVE]
  }

  manageCreep (creep) {
    // Disable notifications of attack since this creep will head into hostile rooms.
    if (!creep.memory.dn) {
      creep.notifyWhenAttacked(false)
    }

    // Delete current target if it is currently visible.
    if (creep.memory.starget && Game.rooms[creep.memory.starget]) {
      delete creep.memory.starget
    }

    // Harass current room by signing controller and stomping contruction sites.
    if (!creep.room.controller || !creep.room.controller.my) {
      if (!creep.memory.stomproom || creep.memory.stomproom !== creep.room.name) {
        creep.memory.stomproom = creep.room.name
        creep.memory.stomptime = Game.time
      }

      if (Game.time - creep.memory.stomptime < 70) {
        // Find and destroy any hostile construction sites
        if (this.stompConstruction(creep)) {
          return
        }
        // Tag the controller
        if (this.signController(creep)) {
          return
        }
      }
    }

    // Move on to the next room
    this.migrateRooms(creep)
  }

  stompConstruction (creep) {
    // Use cached construction site
    if (creep.memory.stomp) {
      let construction = Game.getObjectById(creep.memory.stomp)
      if (construction) {
        creep.travelTo(construction)
        return true
      } else {
        delete creep.memory.stomp
      }
    }
    // Find a new site to stomp, excluding any being stood on.
    const construction = creep.pos.findClosestByRange(FIND_HOSTILE_CONSTRUCTION_SITES, {filter: function (site) {
      return site.pos.getRangeTo(creep) > 0
    }})
    if (!construction) {
      return false
    }
    creep.memory.stomp = construction.id
    creep.travelTo(construction)
    return true
  }

  signController (creep) {
    if (!creep.room.controller) {
      return false
    }
    if (creep.room.controller.sign && creep.room.controller.sign.text === CONTROLLER_MESSAGE) {
      return false
    }
    if (creep.pos.isNearTo(creep.room.controller)) {
      creep.signController(creep.room.controller, CONTROLLER_MESSAGE)
    } else {
      creep.travelTo(creep.room.controller)
    }
    return true
  }

  migrateRooms (creep) {
    let target
    if (creep.memory.starget && creep.memory.starget !== creep.room.name) {
      target = creep.memory.starget
    } else {
      target = Room.getScoutTarget(creep)
    }
    creep.travelTo(new RoomPosition(25, 25, target), {range: 23})
  }
}

module.exports = Spook
<|endoftext|>


<commit_before>import React, { useState, useEffect } from 'react';
import { PropTypes as T } from 'prop-types';
import { connect } from 'react-redux';
import _ from 'lodash';

import { getCountryBbox } from '../../utils/countries';
import { formatThousands } from '../../utils/format';
import config from '../../config';
import { openDownloadModal } from '../../actions/action-creators';

import Header, { LoadingHeader, ErrorHeader } from '../../components/header';
import LoadingMessage from '../../components/loading-message';
import InfoMessage from '../../components/info-message';
import MapComponent from '../../components/map';
import LocationsSource from '../../components/map/locations-source';
import MeasurementsLayer from '../../components/map/measurements-layer';
import Legend from '../../components/map/legend';
import LocationCard from '../locations-hub/location-card';

const defaultLocations = {
  locationFetching: false,
  locationError: null,
  locations: null,
};

const defaultCountry = {
  countryFetching: false,
  countryError: null,
  country: null,
};

function Country(props) {
  const id = props.match.params.name;
  const [
    { locationFetching, locationError, locations },
    setLocations,
  ] = useState(defaultLocations);
  const [{ countryFetching, countryError, country }, setCountry] = useState(
    defaultCountry
  );

  useEffect(() => {
    const fetchLocations = id => {
      setLocations(state => ({
        ...state,
        locationFetching: true,
        locationError: null,
      }));
      let limit = 10000;
      fetch(`${config.api}/locations?limit=${limit}&country=${id}`)
        .then(response => {
          if (response.status >= 400) {
            throw new Error('Bad response');
          }
          return response.json();
        })
        .then(
          json => {
            setLocations(state => ({
              ...state,
              fetched: true,
              locationFetching: false,
              locations: json.results,
            }));
          },
          e => {
            console.log('e', e);
            setLocations(state => ({
              ...state,
              locationFetching: false,
              locationError: e,
            }));
          }
        );
    };

    const fetchCountry = id => {
      setCountry(state => ({
        ...state,
        countryFetching: true,
        countryError: null,
      }));
      fetch(`${config.api}/countries/${id}`)
        .then(response => {
          if (response.status >= 400) {
            throw new Error('Bad response');
          }
          return response.json();
        })
        .then(
          json => {
            setCountry(state => ({
              ...state,
              countryFetching: false,
              country: json.results[0],
            }));
          },
          e => {
            console.log('e', e);
            setCountry(state => ({
              ...state,
              countryFetching: false,
              countryError: e,
            }));
          }
        );
    };

    fetchLocations(id);
    fetchCountry(id);

    return () => {
      setLocations(defaultLocations);
      setCountry(defaultCountry);
    };
  }, [id]);

  function onDownloadClick(data) {
    // e && e.preventDefault();
    props._openDownloadModal(data);
  }

  // gets sources from locations and uses set to create an array with no duplicates
  const locationSources =
    locations &&
    locations
      .map(location => location.sources)
      .flat()
      .filter(source => source !== undefined);
  const sourceList = locations
    ? Array.from(new Set(locationSources.map(source => source.id))).map(
        sourceId => {
          return locationSources.find(source => source.id === sourceId);
        }
      )
    : null;

  let locationGroups = _(locations).sortBy('city').groupBy('city').value();

  return (

      {countryFetching || locationFetching ? (
        <LoadingHeader />
      ) : country && locations && !countryError ? (
        <>
           1 ? 'locations' : 'location',
              },
              {
                number: formatThousands(country.count),
                label: 'measurements',
              },
              {
                number: sourceList.length,
                label: sourceList.length > 1 ? 'sources' : 'source',
              },
            ]}
            action={{
              api: config.apiDocs,
              download: () =>
                onDownloadClick({
                  country: id,
                }),
            }}
          />

                <MapComponent
                  bbox={getCountryBbox(country.code)}
                  scrollZoomDisabled
                >
                  <LocationsSource activeParameter={2}>
                    <MeasurementsLayer
                      activeParameter={2}
                      country={country.code}
                    />
                  </LocationsSource>
                  <Legend
                    activeParameter={{ parameterId: 2, displayName: 'PM2.5' }}
                  />
                </MapComponent>

            {locationFetching ? (
              <LoadingMessage />
            ) : !locationError ? (

                {Object.entries(locationGroups).map(([city, cityLocations]) => (

                          {city}{' '}

                            {cityLocations.length}{' '}
                            {cityLocations.length > 1
                              ? 'locations'
                              : 'location'}

                          <a
                            href="#"
                            className="location-download-button"
                            title={`Download ${city} data`}
                            onClick={() =>
                              onDownloadClick({
                                country: id,
                                area: city,
                              })
                            }
                          >
                            Download

                        {cityLocations.map(loc => {
                          let openModal = () =>
                            onDownloadClick({
                              country: loc.country,
                              area: loc.city,
                              location: loc.id,
                            });
                          return (
                            <LocationCard
                              mobile={loc.isMobile}
                              key={loc.id}
                              city={loc.city}
                              country={loc.country}
                              firstUpdated={loc.firstUpdated}
                              id={loc.id}
                              lastUpdated={loc.lastUpdated}
                              name={loc.name}
                              onDownloadClick={openModal}
                              parametersList={loc.parameters}
                              sources={loc.sources}
                              sourceType={loc.sourceType}
                              totalMeasurements={loc.measurements}
                            />
                          );
                        })}

                ))}

            ) : (
              <InfoMessage standardMessage />
            )}

        </>
      ) : (
        <ErrorHeader />
      )}

  );
}

Country.propTypes = {
  match: T.object,

  _openDownloadModal: T.func,
};

// /////////////////////////////////////////////////////////////////// //
// Connect functions

function dispatcher(dispatch) {
  return {
    _openDownloadModal: (...args) => dispatch(openDownloadModal(...args)),
  };
}

export default connect(null, dispatcher)(Country);
<commit_msg>Display number of sources from endpoint<commit_after>import React, { useState, useEffect } from 'react';
import { PropTypes as T } from 'prop-types';
import { connect } from 'react-redux';
import _ from 'lodash';

import { getCountryBbox } from '../../utils/countries';
import { formatThousands } from '../../utils/format';
import config from '../../config';
import { openDownloadModal } from '../../actions/action-creators';

import Header, { LoadingHeader, ErrorHeader } from '../../components/header';
import LoadingMessage from '../../components/loading-message';
import InfoMessage from '../../components/info-message';
import MapComponent from '../../components/map';
import LocationsSource from '../../components/map/locations-source';
import MeasurementsLayer from '../../components/map/measurements-layer';
import Legend from '../../components/map/legend';
import LocationCard from '../locations-hub/location-card';

const defaultLocations = {
  locationFetching: false,
  locationError: null,
  locations: null,
};

const defaultCountry = {
  countryFetching: false,
  countryError: null,
  country: null,
};

function Country(props) {
  const id = props.match.params.name;
  const [
    { locationFetching, locationError, locations },
    setLocations,
  ] = useState(defaultLocations);
  const [{ countryFetching, countryError, country }, setCountry] = useState(
    defaultCountry
  );

  useEffect(() => {
    const fetchLocations = id => {
      setLocations(state => ({
        ...state,
        locationFetching: true,
        locationError: null,
      }));
      let limit = 10000;
      fetch(`${config.api}/locations?limit=${limit}&country=${id}`)
        .then(response => {
          if (response.status >= 400) {
            throw new Error('Bad response');
          }
          return response.json();
        })
        .then(
          json => {
            setLocations(state => ({
              ...state,
              fetched: true,
              locationFetching: false,
              locations: json.results,
            }));
          },
          e => {
            console.log('e', e);
            setLocations(state => ({
              ...state,
              locationFetching: false,
              locationError: e,
            }));
          }
        );
    };

    const fetchCountry = id => {
      setCountry(state => ({
        ...state,
        countryFetching: true,
        countryError: null,
      }));
      fetch(`${config.api}/countries/${id}`)
        .then(response => {
          if (response.status >= 400) {
            throw new Error('Bad response');
          }
          return response.json();
        })
        .then(
          json => {
            setCountry(state => ({
              ...state,
              countryFetching: false,
              country: json.results[0],
            }));
          },
          e => {
            console.log('e', e);
            setCountry(state => ({
              ...state,
              countryFetching: false,
              countryError: e,
            }));
          }
        );
    };

    fetchLocations(id);
    fetchCountry(id);

    return () => {
      setLocations(defaultLocations);
      setCountry(defaultCountry);
    };
  }, [id]);

  let locationGroups = _(locations).sortBy('city').groupBy('city').value();

  return (

      {countryFetching || locationFetching ? (
        <LoadingHeader />
      ) : country && locations && !countryError ? (
        <>
           1 ? 'locations' : 'location',
              },
              {
                number: formatThousands(country.count),
                label: 'measurements',
              },
              {
                number: country.sources,
                label: country.sources > 1 ? 'sources' : 'source',
              },
            ]}
            action={{
              api: config.apiDocs,
              download: () =>
                props._openDownloadModal({
                  country: id,
                }),
            }}
          />

                <MapComponent
                  bbox={getCountryBbox(country.code)}
                  scrollZoomDisabled
                >
                  <LocationsSource activeParameter={2}>
                    <MeasurementsLayer
                      activeParameter={2}
                      country={country.code}
                    />
                  </LocationsSource>
                  <Legend
                    activeParameter={{ parameterId: 2, displayName: 'PM2.5' }}
                  />
                </MapComponent>

            {locationFetching ? (
              <LoadingMessage />
            ) : !locationError ? (

                {Object.entries(locationGroups).map(([city, cityLocations]) => (

                          {city}{' '}

                            {cityLocations.length}{' '}
                            {cityLocations.length > 1
                              ? 'locations'
                              : 'location'}

                          <a
                            href="#"
                            className="location-download-button"
                            title={`Download ${city} data`}
                            onClick={() =>
                              onDownloadClick({
                                country: id,
                                area: city,
                              })
                            }
                          >
                            Download

                        {cityLocations.map(loc => {
                          let openModal = () =>
                            onDownloadClick({
                              country: loc.country,
                              area: loc.city,
                              location: loc.id,
                            });
                          return (
                            <LocationCard
                              mobile={loc.isMobile}
                              key={loc.id}
                              city={loc.city}
                              country={loc.country}
                              firstUpdated={loc.firstUpdated}
                              id={loc.id}
                              lastUpdated={loc.lastUpdated}
                              name={loc.name}
                              onDownloadClick={openModal}
                              parametersList={loc.parameters}
                              sources={loc.sources}
                              sourceType={loc.sourceType}
                              totalMeasurements={loc.measurements}
                            />
                          );
                        })}

                ))}

            ) : (
              <InfoMessage standardMessage />
            )}

        </>
      ) : (
        <ErrorHeader />
      )}

  );
}

Country.propTypes = {
  match: T.object,

  _openDownloadModal: T.func,
};

// /////////////////////////////////////////////////////////////////// //
// Connect functions

function dispatcher(dispatch) {
  return {
    _openDownloadModal: (...args) => dispatch(openDownloadModal(...args)),
  };
}

export default connect(null, dispatcher)(Country);
<|endoftext|>


<commit_before>#!/usr/bin/env node

var path = require('path');
var findup = require('findup-sync');
var resolve = require('resolve').sync;

var base = process.cwd();

var nwitchPath;
try {
  nwitchPath = resolve('nwitch', {basedir: base});
} catch (error) {
  nwitchPath = findup('lib/index.js');
  if (!nwitchPath) {
    console.error('Unable to find local nwitch.');
  }
}

var configFile = path.resolve(base, './config.toml');

require(nwitchPath)(configFile);<commit_msg>Use logger to log error finding local nwitch<commit_after>#!/usr/bin/env node

var path = require('path');
var findup = require('findup-sync');
var resolve = require('resolve').sync;

var logger = require('../lib/core/logger').logger;

var base = process.cwd();

var nwitchPath;
try {
  nwitchPath = resolve('nwitch', {basedir: base});
} catch (error) {
  nwitchPath = findup('lib/index.js');
  if (!nwitchPath) {
    logger.error('Unable to find local nwitch.');
  }
}

var configFile = path.resolve(base, './config.toml');

require(nwitchPath)(configFile);<|endoftext|>


<commit_before>var express = require('express.io'),
    Twit = require('twit'),
    winston = require('winston');
//change to false if you haven't papertrailapp.com account
var needLogs = true;

if(process.env.consumer_key === undefined){
    var config = require('../config.json');
    if(needLogs === true) var logConfig = require('../logConfig.json');
}
var server = express();

if(needLogs === true){
    var Papertrail = require('winston-papertrail').Papertrail;

    var logger = new winston.Logger({
        transports: [
            new winston.transports.Papertrail({
                host: process.env.url_log || logConfig.env.url_log,
                port: process.env.port_log || logConfig.env.port_log,
                logFormat: function(level, message) {
                    return '<<<' + level + '>>> ' + message;
                }
            })
        ]
    });
}

server.set('port', (process.env.PORT || 5000));

var bot = new Twit({
    consumer_key: process.env.consumer_key || config.env.consumer_key,
    consumer_secret: process.env.consumer_secret || config.env.consumer_secret,
    access_token: process.env.access_token || config.env.access_token,
    access_token_secret: process.env.access_token_secret || config.env.access_token_secret
});
//interval 1 day
var interval = 86400000;
//get date as twitter do
function datestring () {
    var now = new Date();
    return now.getUTCFullYear() + '-' + (now.getUTCMonth() + 1) + '-' + now.getDate();
}

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min)) + min;
}
//params to publish a tweet
function getParams(){
    var today = new Date();
    var switchTweet;
    //Monday new tech
    if(today.getDay() == 1){
        if(getRandomInt(1,2) == 1){
            return {q: 'github.com/',since: datestring(),result_type: 'mixed',language: 'en'};
        }else{
            return {q: 'tcrn.ch/',since: datestring(),result_type: 'mixed'};
        }
    }
    //Tuesday business
    if(today.getDay() == 2){
        if(getRandomInt(1,2) == 1){
            return {q: 'hbr.org/',since: datestring(),result_type: 'mixed'};
        }else{
            return {q: 'mitsmr.com/',since: datestring(),result_type: 'mixed'};
        }
    }
    //Wednesday marketing
    if(today.getDay() == 3){
        if(getRandomInt(1,2) == 1){
            return {q: 'CEO',since: datestring(),result_type: 'mixed',language: 'en'};
        }else{
            return {q: 'company',since: datestring(),result_type: 'mixed',language: 'en'};
        }
    }
    //Thursday hack
    if(today.getDay() == 4){
        switchTweet = getRandomInt(1,3);
        if(switchTweet == 1){
            return {q: 'angularjs',since: datestring(),result_type: 'mixed',language: 'en'};
        }else if(switchTweet == 2){
            return {q: '#startup',since: datestring(),result_type: 'mixed',language: 'en'};
        }else return {q: 'nodejs',since: datestring(),result_type: 'mixed',language: 'en'};
    }
    //Friday,Saturday and Sunday hobby
    if(today.getDay() == 5 || today.getDay() == 6 || today.getDay() == 7){
        switchTweet = getRandomInt(1,12);
        if(switchTweet >= 8){
            return {q: 't.ted.com/',since: datestring(),result_type: 'mixed',language: 'en'};
        }else if(switchTweet < 8 && switchTweet >= 4){
            return {q: 'samaltman.com/',since: datestring(),result_type: 'mixed'};
        }else return {q: 'nasa',since: datestring(),result_type: 'mixed',language: 'es'};
    }
}

setInterval(function() {
    bot.get('followers/ids', function(err, reply) {
      if(err) return handleError(err);
      if(needLogs === true) logger.info('\n# followers:' + reply.ids.length.toString());
    });

    bot.get('search', getParams(), function (err, reply) { //get the most popular tweet
        if(err) return handleError(err);

        var max = 0,
            popular;

        var tweets = reply.results;

        for(i = 0 ; i < tweets.length ; i++){
            var tweet = tweets[i],
                popularity = tweet.metadata.recent_retweets;

            if(popularity > max) {
                max = popularity;
                popular = tweet.text;
            }
        }

        bot.tweet(popular, function (err, reply) { //post the tweet you searched before
            if(err) return handleError(err);
            if(needLogs === true) logger.info('\nTweet: ' + (reply ? reply.text : reply));
        });
    });
}, interval);

setInterval(function() {
    bot.get('followers/ids', function(err, reply) {
      if(err) return handleError(err);
      if(needLogs === true) logger.info('\n# followers:' + reply.ids.length.toString());
    });
    if(getRandomInt(1,2) == 1) {
      bot.mingle(function(err, reply) { //follow
        if(err) return handleError(err);

        var name = reply.screen_name;
        if(needLogs === true) logger.info('\nMingle: followed @' + name);
      });
    } else {
      bot.prune(function(err, reply) { //unfollow
        if(err) return handleError(err);

        var name = reply.screen_name;
        if(needLogs === true) logger.info('\nPrune: unfollowed @'+ name);
      });
    }
}, interval/4);

server.listen(server.get('port'), function() {
    console.log("Node app is running at localhost:" + server.get('port'));
    if(needLogs === true) logger.info("Node app is running at localhost:" + server.get('port'));
});

function handleError(err) {
  if(needLogs === true) logger.info('response status:', err.statusCode);
  if(needLogs === true) logger.info('data:', err.data);
}
<commit_msg>update twitter API<commit_after>var express = require('express.io'),
    Twit = require('twit'),
    winston = require('winston');
//change to false if you haven't papertrailapp.com account
var needLogs = true;

if(process.env.consumer_key === undefined){
    var config = require('../config.json');
    if(needLogs === true) var logConfig = require('../logConfig.json');
}
var server = express();

if(needLogs === true){
    var Papertrail = require('winston-papertrail').Papertrail;

    var logger = new winston.Logger({
        transports: [
            new winston.transports.Papertrail({
                host: process.env.url_log || logConfig.env.url_log,
                port: process.env.port_log || logConfig.env.port_log,
                logFormat: function(level, message) {
                    return '<<<' + level + '>>> ' + message;
                }
            })
        ]
    });
}

server.set('port', (process.env.PORT || 5000));

var bot = new Twit({
    consumer_key: process.env.consumer_key || config.env.consumer_key,
    consumer_secret: process.env.consumer_secret || config.env.consumer_secret,
    access_token: process.env.access_token || config.env.access_token,
    access_token_secret: process.env.access_token_secret || config.env.access_token_secret
});
//interval 1 day
var interval = 86400000;
//get date as twitter do
function datestring () {
    var now = new Date();
    return now.getUTCFullYear() + '-' + (now.getUTCMonth() + 1) + '-' + now.getDate();
}

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min)) + min;
}
//params to publish a tweet
function getParams(){
    var today = new Date();
    var switchTweet;
    //Monday new tech
    if(today.getDay() == 1){
        if(getRandomInt(1,2) == 1){
            return {q: 'github.com/',since: datestring(),language: 'en'};
        }else{
            return {q: 'tcrn.ch/',since: datestring()};
        }
    }
    //Tuesday business
    if(today.getDay() == 2){
        if(getRandomInt(1,2) == 1){
            return {q: 'hbr.org/',since: datestring()};
        }else{
            return {q: 'mitsmr.com/',since: datestring()};
        }
    }
    //Wednesday marketing
    if(today.getDay() == 3){
        if(getRandomInt(1,2) == 1){
            return {q: 'CEO',since: datestring(),language: 'en'};
        }else{
            return {q: 'company',since: datestring(),language: 'en'};
        }
    }
    //Thursday hack
    if(today.getDay() == 4){
        switchTweet = getRandomInt(1,3);
        if(switchTweet == 1){
            return {q: '#angularjs',since: datestring(),language: 'en'};
        }else if(switchTweet == 2){
            return {q: '#startup',since: datestring(),language: 'en'};
        }else return {q: '#nodejs',since: datestring(),language: 'en'};
    }
    //Friday,Saturday and Sunday hobby
    if(today.getDay() == 5 || today.getDay() == 6 || today.getDay() == 7){
        switchTweet = getRandomInt(1,12);
        if(switchTweet >= 8){
            return {q: 't.ted.com/',since: datestring(),language: 'en'};
        }else if(switchTweet < 8 && switchTweet >= 4){
            return {q: 'samaltman.com/',since: datestring()};
        }else return {q: 'nasa',since: datestring(),language: 'es'};
    }
}

setInterval(function() {
    bot.get('followers/ids', function(err, reply) {
      if(err) return handleError(err);
      if(needLogs === true) logger.info('\n# followers:' + reply.ids.length.toString());
    });

    bot.get('search/tweets', getParams(), function (err, reply) { //get the most popular tweet
        if(err) return handleError(err);

        var max = 0,
            popular;

        var tweets = reply.statuses;

        for(i = 0 ; i < tweets.length ; i++){
            var tweet = tweets[i],
                popularity = tweet.retweet_count;

            if(popularity > max) {
                max = popularity;
                popular = tweet.text;
            }
        }

        bot.post('statuses/update', { status: popular }, function(err, data, response) {
            if(err) return handleError(err);
            if(needLogs === true) logger.info('\nTweet: ' + (reply ? reply.text : reply));
        });
    });
}, interval);
//
// setInterval(function() {
//     bot.get('followers/ids', function(err, reply) {
//       if(err) return handleError(err);
//       if(needLogs === true) logger.info('\n# followers:' + reply.ids.length.toString());
//     });
//     if(getRandomInt(1,2) == 1) {
//       bot.prototype.mingle = function (callback) { //follow a random follower of your friends
//         bot.get('followers/ids', function(err, reply) {
//             if(err) { return callback(err); }
//
//             var followers = reply.ids,
//                 randFollower  = randIndex(followers);
//
//             bot.get('friends/ids', { user_id: randFollower }, function(err, reply) {
//                 if(err) { return callback(err); }
//
//                 var friends = reply.ids,
//                     target  = randIndex(friends);
//
//                 if(needLogs === true) logger.info('\nFriend: follow @'+ reply.screen_name);
//
//                 bot.post('friendships/create', { id: target }, callback);
//             });
//         });
//       };
//     } else {
//       bot.prototype.prune = function (callback) { //unfollow wich is not following you
//         bot.get('followers/ids', function(err, reply) {
//             if(err) return callback(err);
//
//             var followers = reply.ids;
//
//             bot.get('friends/ids', function(err, reply) {
//                 if(err) return callback(err);
//
//                 var friends = reply.ids,
//                     pruned = false;
//
//                 while(!pruned) {
//                   var target = randIndex(friends);
//
//                   if(!~followers.indexOf(target)) {
//                     pruned = true;
//                     bot.post('friendships/destroy', { id: target }, callback);
//                     if(needLogs === true) logger.info('\nPurge: unfollow @'+ reply.screen_name);
//                   }
//                 }
//             });
//         });
//       };
//     }
// }, interval/4);

server.listen(server.get('port'), function() {
    console.log("Node app is running at localhost:" + server.get('port'));
    if(needLogs === true) logger.info("Node app is running at localhost:" + server.get('port'));
});

function handleError(err) {
  if(needLogs === true) logger.info('response status:', err.statusCode);
  if(needLogs === true) logger.info('data:', err.data);
}
<|endoftext|>


<commit_before>import React, {Component, PropTypes} from 'react'
import {withRouter} from 'react-router'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'

import {isUserAuthorized, MEMBER_ROLE, VIEWER_ROLE} from 'src/auth/Authorized'

import {showDatabases} from 'shared/apis/metaQuery'

import {getSourcesAsync} from 'shared/actions/sources'
import {errorThrown as errorThrownAction} from 'shared/actions/errors'
import {publishAutoDismissingNotification} from 'shared/dispatchers'

import {DEFAULT_HOME_PAGE} from 'shared/constants'

// Acts as a 'router middleware'. The main `App` component is responsible for
// getting the list of data nodes, but not every page requires them to function.
// Routes that do require data nodes can be nested under this component.
class CheckSources extends Component {
  constructor(props) {
    super(props)

    this.state = {
      isFetching: true,
    }
  }

  getChildContext() {
    const {sources, params: {sourceID}} = this.props
    return {source: sources.find(s => s.id === sourceID)}
  }

  async componentWillMount() {
    const {auth: {isUsingAuth, me}} = this.props

    if (!isUsingAuth || isUserAuthorized(me.role, VIEWER_ROLE)) {
      await this.props.getSources()
    }

    this.setState({isFetching: false})
  }

  shouldComponentUpdate(nextProps) {
    const {auth: {isUsingAuth, me}} = nextProps
    // don't update this component if currentOrganization is what has changed,
    // or else the app will try to call showDatabases in componentWillUpdate,
    // which will fail unless sources have been refreshed
    if (
      isUsingAuth &&
      me.currentOrganization.id !== this.props.auth.me.currentOrganization.id
    ) {
      return false
    }
    return true
  }

  async componentWillUpdate(nextProps, nextState) {
    const {
      router,
      location,
      params,
      errorThrown,
      sources,
      auth: {isUsingAuth, me},
      notify,
    } = nextProps
    const {isFetching} = nextState
    const source = sources.find(s => s.id === params.sourceID)
    const defaultSource = sources.find(s => s.default === true)

    if (
      !isFetching &&
      isUsingAuth &&
      me.role === MEMBER_ROLE &&
      !me.superAdmin
    ) {
      // if you're a member, go to purgatory.
      return router.push('/purgatory')
    }

    if (!isFetching && !source) {
      const rest = location.pathname.match(/\/sources\/\d+?\/(.+)/)
      const restString = rest === null ? DEFAULT_HOME_PAGE : rest[1]

      if (isUsingAuth && me.role === VIEWER_ROLE && !me.superAdmin) {
        if (defaultSource) {
          return router.push(`/sources/${defaultSource.id}/${restString}`)
        } else if (sources[0]) {
          return router.push(`/sources/${sources[0].id}/${restString}`)
        }
        // if you're a viewer and there are no sources, go to purgatory.
        notify('error', 'Organization has no sources configured')
        return router.push('/purgatory')
      }

      // if you're an editor or not using auth, try for sources or otherwise
      // create one
      if (defaultSource) {
        return router.push(`/sources/${defaultSource.id}/${restString}`)
      } else if (sources[0]) {
        return router.push(`/sources/${sources[0].id}/${restString}`)
      }

      return router.push(`/sources/new?redirectPath=${location.pathname}`)
    }

    if (!isFetching && !location.pathname.includes('/manage-sources')) {
      // Do simple query to proxy to see if the source is up.
      try {
        // the guard around currentOrganization prevents this showDatabases
        // invocation since sources haven't been refreshed yet
        await showDatabases(source.links.proxy)
      } catch (error) {
        errorThrown(error, 'Unable to connect to source')
      }
    }
  }

  render() {
    const {
      params,
      sources,
      auth: {isUsingAuth, me: {currentOrganization}},
    } = this.props
    const {isFetching} = this.state
    const source = sources.find(s => s.id === params.sourceID)

    if (isFetching || !source || (isUsingAuth && !currentOrganization)) {
      return

    }

    // TODO: guard against invalid resource access

    return (
      this.props.children &&
      React.cloneElement(
        this.props.children,
        Object.assign({}, this.props, {
          source,
        })
      )
    )
  }
}

const {arrayOf, bool, func, node, shape, string} = PropTypes

CheckSources.propTypes = {
  getSources: func.isRequired,
  sources: arrayOf(
    shape({
      links: shape({
        proxy: string.isRequired,
        self: string.isRequired,
        kapacitors: string.isRequired,
        queries: string.isRequired,
        permissions: string.isRequired,
        users: string.isRequired,
        databases: string.isRequired,
      }).isRequired,
    })
  ),
  children: node,
  params: shape({
    sourceID: string,
  }).isRequired,
  router: shape({
    push: func.isRequired,
  }).isRequired,
  location: shape({
    pathname: string.isRequired,
  }).isRequired,
  auth: shape({
    isUsingAuth: bool,
    me: shape({
      currentOrganization: shape({
        name: string.isRequired,
        id: string.isRequired,
      }),
    }),
  }),
  notify: func.isRequired,
}

CheckSources.childContextTypes = {
  source: shape({
    links: shape({
      proxy: string.isRequired,
      self: string.isRequired,
      kapacitors: string.isRequired,
      queries: string.isRequired,
      permissions: string.isRequired,
      users: string.isRequired,
      databases: string.isRequired,
    }).isRequired,
  }),
}

const mapStateToProps = ({sources, auth}) => ({
  sources,
  auth,
})

const mapDispatchToProps = dispatch => ({
  getSources: bindActionCreators(getSourcesAsync, dispatch),
  errorThrown: bindActionCreators(errorThrownAction, dispatch),
  notify: bindActionCreators(publishAutoDismissingNotification, dispatch),
})

export default connect(mapStateToProps, mapDispatchToProps)(
  withRouter(CheckSources)
)
<commit_msg>Route demoted admin to / from /admin-chronograf<commit_after>import React, {Component, PropTypes} from 'react'
import {withRouter} from 'react-router'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'

import {
  isUserAuthorized,
  MEMBER_ROLE,
  VIEWER_ROLE,
  ADMIN_ROLE,
} from 'src/auth/Authorized'

import {showDatabases} from 'shared/apis/metaQuery'

import {getSourcesAsync} from 'shared/actions/sources'
import {errorThrown as errorThrownAction} from 'shared/actions/errors'
import {publishAutoDismissingNotification} from 'shared/dispatchers'

import {DEFAULT_HOME_PAGE} from 'shared/constants'

// Acts as a 'router middleware'. The main `App` component is responsible for
// getting the list of data nodes, but not every page requires them to function.
// Routes that do require data nodes can be nested under this component.
class CheckSources extends Component {
  constructor(props) {
    super(props)

    this.state = {
      isFetching: true,
    }
  }

  getChildContext() {
    const {sources, params: {sourceID}} = this.props
    return {source: sources.find(s => s.id === sourceID)}
  }

  async componentWillMount() {
    const {auth: {isUsingAuth, me}} = this.props

    if (!isUsingAuth || isUserAuthorized(me.role, VIEWER_ROLE)) {
      await this.props.getSources()
    }

    this.setState({isFetching: false})
  }

  shouldComponentUpdate(nextProps) {
    const {auth: {isUsingAuth, me}} = nextProps
    // don't update this component if currentOrganization is what has changed,
    // or else the app will try to call showDatabases in componentWillUpdate,
    // which will fail unless sources have been refreshed
    if (
      isUsingAuth &&
      me.currentOrganization.id !== this.props.auth.me.currentOrganization.id
    ) {
      return false
    }
    return true
  }

  async componentWillUpdate(nextProps, nextState) {
    const {
      router,
      location,
      params,
      errorThrown,
      sources,
      auth: {isUsingAuth, me},
      notify,
    } = nextProps
    const {isFetching} = nextState
    const source = sources.find(s => s.id === params.sourceID)
    const defaultSource = sources.find(s => s.default === true)

    if (
      isUserAuthorized(this.props.auth.me.role, ADMIN_ROLE) &&
      !isUserAuthorized(nextProps.auth.me.role, ADMIN_ROLE)
    ) {
      return router.push('/')
    }

    if (
      !isFetching &&
      isUsingAuth &&
      me.role === MEMBER_ROLE &&
      !me.superAdmin
    ) {
      // if you're a member, go to purgatory.
      return router.push('/purgatory')
    }

    if (!isFetching && !source) {
      const rest = location.pathname.match(/\/sources\/\d+?\/(.+)/)
      const restString = rest === null ? DEFAULT_HOME_PAGE : rest[1]

      if (isUsingAuth && me.role === VIEWER_ROLE && !me.superAdmin) {
        if (defaultSource) {
          return router.push(`/sources/${defaultSource.id}/${restString}`)
        } else if (sources[0]) {
          return router.push(`/sources/${sources[0].id}/${restString}`)
        }
        // if you're a viewer and there are no sources, go to purgatory.
        notify('error', 'Organization has no sources configured')
        return router.push('/purgatory')
      }

      // if you're an editor or not using auth, try for sources or otherwise
      // create one
      if (defaultSource) {
        return router.push(`/sources/${defaultSource.id}/${restString}`)
      } else if (sources[0]) {
        return router.push(`/sources/${sources[0].id}/${restString}`)
      }

      return router.push(`/sources/new?redirectPath=${location.pathname}`)
    }

    if (!isFetching && !location.pathname.includes('/manage-sources')) {
      // Do simple query to proxy to see if the source is up.
      try {
        // the guard around currentOrganization prevents this showDatabases
        // invocation since sources haven't been refreshed yet
        await showDatabases(source.links.proxy)
      } catch (error) {
        errorThrown(error, 'Unable to connect to source')
      }
    }
  }

  render() {
    const {
      params,
      sources,
      auth: {isUsingAuth, me: {currentOrganization}},
    } = this.props
    const {isFetching} = this.state
    const source = sources.find(s => s.id === params.sourceID)

    if (isFetching || !source || (isUsingAuth && !currentOrganization)) {
      return

    }

    // TODO: guard against invalid resource access

    return (
      this.props.children &&
      React.cloneElement(
        this.props.children,
        Object.assign({}, this.props, {
          source,
        })
      )
    )
  }
}

const {arrayOf, bool, func, node, shape, string} = PropTypes

CheckSources.propTypes = {
  getSources: func.isRequired,
  sources: arrayOf(
    shape({
      links: shape({
        proxy: string.isRequired,
        self: string.isRequired,
        kapacitors: string.isRequired,
        queries: string.isRequired,
        permissions: string.isRequired,
        users: string.isRequired,
        databases: string.isRequired,
      }).isRequired,
    })
  ),
  children: node,
  params: shape({
    sourceID: string,
  }).isRequired,
  router: shape({
    push: func.isRequired,
  }).isRequired,
  location: shape({
    pathname: string.isRequired,
  }).isRequired,
  auth: shape({
    isUsingAuth: bool,
    me: shape({
      currentOrganization: shape({
        name: string.isRequired,
        id: string.isRequired,
      }),
    }),
  }),
  notify: func.isRequired,
}

CheckSources.childContextTypes = {
  source: shape({
    links: shape({
      proxy: string.isRequired,
      self: string.isRequired,
      kapacitors: string.isRequired,
      queries: string.isRequired,
      permissions: string.isRequired,
      users: string.isRequired,
      databases: string.isRequired,
    }).isRequired,
  }),
}

const mapStateToProps = ({sources, auth}) => ({
  sources,
  auth,
})

const mapDispatchToProps = dispatch => ({
  getSources: bindActionCreators(getSourcesAsync, dispatch),
  errorThrown: bindActionCreators(errorThrownAction, dispatch),
  notify: bindActionCreators(publishAutoDismissingNotification, dispatch),
})

export default connect(mapStateToProps, mapDispatchToProps)(
  withRouter(CheckSources)
)
<|endoftext|>


<commit_before>/* jshint shadow: true */
'use strict';

var createPlot          = require('gl-plot3d'),
    m4FromQuat          = require('gl-mat4/fromQuat'),
    createAxesOptions   = require('./convert/axes'),
    createSpikeOptions  = require('./convert/spikes'),
    createScatterTrace  = require('./convert/scatter'),
    createSurfaceTrace  = require('./convert/surface'),
    computeTickMarks    = require('./lib/tick-marks'),
    createCamera        = require('./lib/camera'),
    str2RGBAarray       = require('./lib/str2rgbarray'),
    Plotly              = require('../plotly');

function render(scene) {
    computeTickMarks(scene);
    scene.glplot.axes.update(scene.axesOptions);

    var keys = Object.keys(scene.traces);
    for (var i = 0; i < keys.length; ++i) {
        var trace = scene.traces[keys[i]];
        trace.handlePick(scene.glplot.selection);

        if (trace.setContourLevels) trace.setContourLevels();
    }
}

function Scene(options, fullLayout) {

    //Create sub container for plot
    var sceneContainer = document.createElement('div');
    var plotContainer = options.container;

    /*
     * Tag the container with the sceneID
     */
    sceneContainer.id             = options.id;
    sceneContainer.style.position = 'absolute';
    sceneContainer.style.top      = sceneContainer.style.left = '0px';
    sceneContainer.style.width    = sceneContainer.style.height = '100%';
    plotContainer.appendChild(sceneContainer);

    this.fullLayout               = fullLayout;
    this.id                       = options.id || 'scene';
    /*
     * Move this to calc step? Why does it work here?
     */
    this.axesOptions      = createAxesOptions(fullLayout[this.id]);
    this.spikeOptions     = createSpikeOptions(fullLayout[this.id]);
    this.container        = sceneContainer;

    var glplotOptions = {
            container:  sceneContainer,
            axes:       this.axesOptions,
            spikes:     this.spikeOptions,
            pickRadius: 10,
            snapToData: true,
            autoScale:  true,
            autoBounds: false
    };

    if (options.staticPlot) {
        glplotOptions.pixelRatio = options.plot3dPixelRatio;
        glplotOptions.glOptions = {
            preserveDrawingBuffer: true,
            premultipliedAlpha:true
        };
    }

    try {
        this.glplot = createPlot(glplotOptions);
    } catch (e) {

        /*
         * createPlot will throw when webgl is not enabled in the client.
         * Lets return an instance of the module with all functions noop'd.
         * The destroy method - which will remove the container from the DOM
         * is overridden with a function that removes the container only.
         */
        var noop = function () {};
        for (var prop in this) if (typeof this[prop] === 'function') this[prop] = noop;
        this.destroy = function () {
            this.container.parentNode.removeChild(this.container);
        };

        var div = document.createElement('div');
        div.textContent = 'Webgl is not supported by your browser - visit http://get.webgl.org for more info';
        div.style.cursor = 'pointer';
        div.style.fontSize = '24px';
        div.style.color = Plotly.Color.defaults[0];

        this.container.appendChild(div);
        this.container.style.background = '#FFFFFF';
        this.container.onclick = function () {
            window.open('http://get.webgl.org');
        };

        /*
         * return before setting up camera and onrender methods
         */
        return;
    }

    var cameraPos;

    if(fullLayout.scene.cameraposition !== undefined) {
        cameraPos = this.cleanCamera(fullLayout.scene.cameraposition);
    }
    else cameraPos = fullLayout.scene.camera;

    this.camera = createCamera(this.container, {
        center: [cameraPos.center.x, cameraPos.center.y, cameraPos.center.z],
        eye:    [cameraPos.eye.x, cameraPos.eye.y, cameraPos.eye.z],
        up:     [cameraPos.up.x, cameraPos.up.y, cameraPos.up.z],
        zoomMin: 0.1,
        zoomMax: 100,
        mode:   'orbit'
    });

    this.glplot.camera = this.camera;

    this.glplot.onrender = render.bind(null, this);

    //List of scene objects
    this.traces = {};

    this.contourLevels = [ [], [], [] ];
}

var proto = Scene.prototype;

var axisProperties = [ 'xaxis', 'yaxis', 'zaxis' ];

proto.plot = function(sceneData, fullLayout, layout) {

    var data, trace;
    var i, j;
    var fullSceneLayout = fullLayout[this.id];
    var sceneLayout = layout[this.id];

    if (fullSceneLayout.bgcolor) this.glplot.clearColor = str2RGBAarray(fullSceneLayout.bgcolor);
    else this.glplot.clearColor = [0, 0, 0, 0];

    //Update layout
    this.fullSceneLayout = fullSceneLayout;

    this.glplotLayout = fullSceneLayout;
    this.axesOptions.merge(fullSceneLayout);
    this.spikeOptions.merge(fullSceneLayout);

    //Update scene
    this.glplot.update({});

    // Update axes functions BEFORE updating traces
    for (i = 0; i < 3; ++i) {
        var axis = fullSceneLayout[axisProperties[i]];
        Plotly.Gl3dAxes.setConvert(axis);
    }

    //Update traces
    if (sceneData) {
        if(!Array.isArray(sceneData)) sceneData = [sceneData];

        for(i = 0; i < sceneData.length; ++i) {
            data = sceneData[i];
            if(data.visible!==true) {
                continue;
            }
            trace = this.traces[data.uid];
            if(trace) {
                trace.update(data);
            } else {
                switch(data.type) {
                    case 'scatter3d':
                        trace = createScatterTrace(this, data);
                    break;

                    case 'surface':
                        trace = createSurfaceTrace(this, data);
                    break;

                    default:
                }
                this.traces[data.uid] = trace;
            }
        }
    } else {
        sceneData = [];
    }

    var traceIds = Object.keys(this.traces);
trace_id_loop:
    for(i = 0; i<traceIds.length; ++i) {
        for(j = 0; j<sceneData.length; ++j) {
            if(sceneData[j].uid === traceIds[i] && sceneData[j].visible===true) {
                continue trace_id_loop;
            }
        }
        trace = this.traces[traceIds[i]];
        trace.dispose();
        delete this.traces[traceIds[i]];
    }

    //Update ranges (needs to be called *after* objects are added due to updates)
    var sceneBounds = this.glplot.bounds,
        axisDataRange = [];

    for(i = 0; i < 3; ++i) {
        var axis = fullSceneLayout[axisProperties[i]];

        if(axis.autorange) {
            sceneBounds[0][i] = Infinity;
            sceneBounds[1][i] = -Infinity;
            for(j = 0; j < this.glplot.objects.length; ++j) {
                var objBounds = this.glplot.objects[j].bounds;
                sceneBounds[0][i] = Math.min(sceneBounds[0][i], objBounds[0][i]);
                sceneBounds[1][i] = Math.max(sceneBounds[1][i], objBounds[1][i]);
            }
            if('rangemode' in axis && axis.rangemode === 'tozero') {
                sceneBounds[0][i] = Math.min(sceneBounds[0][i], 0);
                sceneBounds[1][i] = Math.max(sceneBounds[1][i], 0);
            }
            if(sceneBounds[0][i] > sceneBounds[1][i]) {
                sceneBounds[0][i] = -1;
                sceneBounds[1][i] =  1;
            } else {
                var d = sceneBounds[1][i] - sceneBounds[0][i];
                sceneBounds[0][i] -= d/32.0;
                sceneBounds[1][i] += d/32.0;
            }
        } else {
            var range = fullSceneLayout[axisProperties[i]].range;
            sceneBounds[0][i] = range[0];
            sceneBounds[1][i] = range[1];
        }
        if(sceneBounds[0][i] === sceneBounds[1][i]) {
            sceneBounds[0][i] -= 1;
            sceneBounds[1][i] += 1;
        }
        axisDataRange[i] = sceneBounds[1][i] - sceneBounds[0][i];
    }

    var axesScaleRatio = [],
        maxRange = Math.max.apply(null, axisDataRange);

    for (i = 0; i < 3; ++i) axesScaleRatio[i] = axisDataRange[i] / maxRange;

    /*
     * Dynamically set the aspect ratio depending on the users aspect settings
     */
    var axisAutoScaleFactor = 4;
    var aspectRatio;

    if (fullSceneLayout.aspectmode === 'auto') {
        if (Math.max.apply(null, axesScaleRatio)/Math.min.apply(null, axesScaleRatio) <= axisAutoScaleFactor) {

            /*
             * USE DATA MODE WHEN AXIS RANGE DIMENSIONS ARE RELATIVELY EQUAL
             */
            aspectRatio = axesScaleRatio;
        } else {

            /*
             * USE EQUAL MODE WHEN AXIS RANGE DIMENSIONS ARE HIGHLY UNEQUAL
             */
            aspectRatio = [1, 1, 1];
        }

    } else if (fullSceneLayout.aspectmode === 'cube') {
        aspectRatio = [1, 1, 1];

    } else if (fullSceneLayout.aspectmode === 'data') {
        aspectRatio = axesScaleRatio;

    } else if (fullSceneLayout.aspectmode === 'manual') {
        var userRatio = fullSceneLayout.aspectratio;
        aspectRatio = [userRatio.x, userRatio.y, userRatio.z];

    } else {
        throw new Error('scene.js aspectRatio was not one of the enumerated types');
    }

    /*
     * Write aspect Ratio back to user data and fullLayout so that it is modifies as user
     * manipulates the aspectmode settings and the fullLayout is up-to-date.
     */
    fullSceneLayout.aspectratio.x = sceneLayout.aspectratio.x = aspectRatio[0];
    fullSceneLayout.aspectratio.y = sceneLayout.aspectratio.y = aspectRatio[1];
    fullSceneLayout.aspectratio.z = sceneLayout.aspectratio.z = aspectRatio[2];

    /*
     * Finally assign the computed aspecratio to the glplot module. This will have an effect
     * on the next render cycle.
     */
    this.glplot.aspect = aspectRatio;

    //Update frame position for multi plots
    var domain = fullSceneLayout.domain || null,
        size = fullLayout._size || null;

    if (domain && size) {
        var containerStyle = this.container.style;
        containerStyle.position = 'absolute';
        containerStyle.left     = (size.l + domain.x[0] * size.w) + 'px';
        containerStyle.top      = (size.t + (1 - domain.y[1]) * size.h) + 'px';
        containerStyle.width    = (size.w * (domain.x[1] - domain.x[0])) + 'px';
        containerStyle.height   = (size.h * (domain.y[1] - domain.y[0])) + 'px';
    }
};

proto.destroy = function() {
    this.glplot.dispose();
    this.container.parentNode.removeChild(this.container);
};

// for reset camera button in modebar
proto.setCameraToDefault = function setCameraToDefault () {
    this.glplot.camera.lookAt(
        [1.25, 1.25, 1.25],
        [0   , 0   , 0   ],
        [0   , 0   , 1   ]
    );
};

// get camera position in plotly coords from 'orbit-camera' coords
proto.getCameraPosition = function getCameraPosition () {
    this.glplot.camera.view.recalcMatrix(this.camera.view.lastT());

    var up     = this.glplot.camera.up;
    var center = this.glplot.camera.center;
    var eye    = this.glplot.camera.eye;

    return {
        up:     {x:up[0], y:up[1], z:up[2]},
        center: {x:center[0], y:center[1], z:center[2]},
        eye:    {x:eye[0], y:eye[1], z:eye[2]}
    };
};

// set camera position with a set of plotly coords
proto.setCameraPosition = function setCameraPosition (camera) {
    var up      = camera.up;
    var center  = camera.center;
    var eye     = camera.eye;
    this.glplot.camera.lookAt(
      [eye.x, eye.y, eye.z],
      [center.x, center.y, center.z],
      [up.x, up.y, up.z]
    );
};

// save camera to user layout (i.e. gd.layout)
proto.saveCamera = function saveCamera(layout) {
    var cameraposition = this.getCameraPosition();

    // save new camera api
    Plotly.Lib.nestedProperty(layout, this.id + '.camera')
        .set(cameraposition);

    // delete old
    delete layout.scene.cameraposition;
};

// convert old camera position api
proto.cleanCamera = function(cameraposition) {
    if (Array.isArray(cameraposition) && cameraposition[0].length === 4) {
        var rotation = cameraposition[0];
        var center   = cameraposition[1];
        var radius   = cameraposition[2];
        var mat = m4FromQuat([], rotation);
        var eye = [];
        for (var i = 0; i < 3; ++i) {
            eye[i] = center[i] + radius * mat[2+4*i];
        }
        return {
            eye: {x: eye[0], y: eye[1], z: eye[2]},
            center: {x: center[0], y: center[1], z: center[2]},
            up: {x: mat[1], y: mat[5], z: mat[9]}
        };
    }
    else return null;
};

proto.toImage = function (format) {
    if (!format) format = 'png';

    var gl = this.glplot.gl;
    var w = gl.drawingBufferWidth;
    var h = gl.drawingBufferHeight;

    gl.bindFramebuffer(gl.FRAMEBUFFER, null);

    var pixels = new Uint8Array(w * h * 4);
    gl.readPixels(0, 0, w, h, gl.RGBA, gl.UNSIGNED_BYTE, pixels);

    //Flip pixels
    for(var j=0,k=h-1; j<k; ++j, --k) {
        for(var i=0; i<w; ++i) {
            for(var l=0; l<4; ++l) {
                var tmp = pixels[4*(w*j+i)+l];
                pixels[4*(w*j+i)+l] = pixels[4*(w*k+i)+l];
                pixels[4*(w*k+i)+l] = tmp;
            }
        }
    }

    var canvas = document.createElement('canvas');
    canvas.width = w;
    canvas.height = h;
    var context = canvas.getContext('2d');
    var imageData = context.createImageData(w, h);
    imageData.data.set(pixels);
    context.putImageData(imageData, 0, 0);

    var dataURL;

    switch (format) {
        case 'jpeg':
            dataURL = canvas.toDataURL('image/jpeg');
            break;
        case 'webp':
            dataURL = canvas.toDataURL('image/webp');
            break;
        default:
        dataURL = canvas.toDataURL('image/png');
    }

    return dataURL;
};

module.exports = Scene;
<commit_msg>lint and comments in Scene<commit_after>/* jshint shadow: true */
'use strict';

var createPlot          = require('gl-plot3d'),
    m4FromQuat          = require('gl-mat4/fromQuat'),
    createAxesOptions   = require('./convert/axes'),
    createSpikeOptions  = require('./convert/spikes'),
    createScatterTrace  = require('./convert/scatter'),
    createSurfaceTrace  = require('./convert/surface'),
    computeTickMarks    = require('./lib/tick-marks'),
    createCamera        = require('./lib/camera'),
    str2RGBAarray       = require('./lib/str2rgbarray'),
    Plotly              = require('../plotly');

function render(scene) {
    computeTickMarks(scene);
    scene.glplot.axes.update(scene.axesOptions);

    var keys = Object.keys(scene.traces);
    for (var i = 0; i < keys.length; ++i) {
        var trace = scene.traces[keys[i]];
        trace.handlePick(scene.glplot.selection);

        if (trace.setContourLevels) trace.setContourLevels();
    }
}

function Scene(options, fullLayout) {

    //Create sub container for plot
    var sceneContainer = document.createElement('div');
    var plotContainer = options.container;

    /*
     * Tag the container with the sceneID
     */
    sceneContainer.id             = options.id;
    sceneContainer.style.position = 'absolute';
    sceneContainer.style.top      = sceneContainer.style.left = '0px';
    sceneContainer.style.width    = sceneContainer.style.height = '100%';
    plotContainer.appendChild(sceneContainer);

    this.fullLayout               = fullLayout;
    this.id                       = options.id || 'scene';
    /*
     * Move this to calc step? Why does it work here?
     */
    this.axesOptions      = createAxesOptions(fullLayout[this.id]);
    this.spikeOptions     = createSpikeOptions(fullLayout[this.id]);
    this.container        = sceneContainer;

    var glplotOptions = {
            container:  sceneContainer,
            axes:       this.axesOptions,
            spikes:     this.spikeOptions,
            pickRadius: 10,
            snapToData: true,
            autoScale:  true,
            autoBounds: false
    };

    if (options.staticPlot) {
        glplotOptions.pixelRatio = options.plot3dPixelRatio;
        glplotOptions.glOptions = {
            preserveDrawingBuffer: true,
            premultipliedAlpha:true
        };
    }

    try {
        this.glplot = createPlot(glplotOptions);
    } catch (e) {

        /*
         * createPlot will throw when webgl is not enabled in the client.
         * Lets return an instance of the module with all functions noop'd.
         * The destroy method - which will remove the container from the DOM
         * is overridden with a function that removes the container only.
         */
        var noop = function () {};
        for (var prop in this) if (typeof this[prop] === 'function') this[prop] = noop;
        this.destroy = function () {
            this.container.parentNode.removeChild(this.container);
        };

        var div = document.createElement('div');
        div.textContent = 'Webgl is not supported by your browser - visit http://get.webgl.org for more info';
        div.style.cursor = 'pointer';
        div.style.fontSize = '24px';
        div.style.color = Plotly.Color.defaults[0];

        this.container.appendChild(div);
        this.container.style.background = '#FFFFFF';
        this.container.onclick = function () {
            window.open('http://get.webgl.org');
        };

        /*
         * return before setting up camera and onrender methods
         */
        return;
    }

    var cameraPos;

    if(fullLayout.scene.cameraposition !== undefined) {
        cameraPos = this.cleanCamera(fullLayout.scene.cameraposition);
    }
    else cameraPos = fullLayout.scene.camera;

    this.camera = createCamera(this.container, {
        center: [cameraPos.center.x, cameraPos.center.y, cameraPos.center.z],
        eye:    [cameraPos.eye.x, cameraPos.eye.y, cameraPos.eye.z],
        up:     [cameraPos.up.x, cameraPos.up.y, cameraPos.up.z],
        zoomMin: 0.1,
        zoomMax: 100,
        mode:   'orbit'
    });

    this.glplot.camera = this.camera;

    this.glplot.onrender = render.bind(null, this);

    //List of scene objects
    this.traces = {};

    this.contourLevels = [ [], [], [] ];
}

var proto = Scene.prototype;

var axisProperties = [ 'xaxis', 'yaxis', 'zaxis' ];

proto.plot = function(sceneData, fullLayout, layout) {

    var data, trace;
    var i, j;
    var fullSceneLayout = fullLayout[this.id];
    var sceneLayout = layout[this.id];

    if (fullSceneLayout.bgcolor) this.glplot.clearColor = str2RGBAarray(fullSceneLayout.bgcolor);
    else this.glplot.clearColor = [0, 0, 0, 0];

    //Update layout
    this.fullSceneLayout = fullSceneLayout;

    this.glplotLayout = fullSceneLayout;
    this.axesOptions.merge(fullSceneLayout);
    this.spikeOptions.merge(fullSceneLayout);

    //Update scene
    this.glplot.update({});

    // Update axes functions BEFORE updating traces
    for (i = 0; i < 3; ++i) {
        var axis = fullSceneLayout[axisProperties[i]];
        Plotly.Gl3dAxes.setConvert(axis);
    }

    //Update traces
    if (sceneData) {
        if(!Array.isArray(sceneData)) sceneData = [sceneData];

        for(i = 0; i < sceneData.length; ++i) {
            data = sceneData[i];
            if(data.visible!==true) {
                continue;
            }
            trace = this.traces[data.uid];
            if(trace) {
                trace.update(data);
            } else {
                switch(data.type) {
                    case 'scatter3d':
                        trace = createScatterTrace(this, data);
                    break;

                    case 'surface':
                        trace = createSurfaceTrace(this, data);
                    break;

                    default:
                }
                this.traces[data.uid] = trace;
            }
        }
    } else {
        sceneData = [];
    }

    var traceIds = Object.keys(this.traces);
trace_id_loop:
    for(i = 0; i<traceIds.length; ++i) {
        for(j = 0; j<sceneData.length; ++j) {
            if(sceneData[j].uid === traceIds[i] && sceneData[j].visible===true) {
                continue trace_id_loop;
            }
        }
        trace = this.traces[traceIds[i]];
        trace.dispose();
        delete this.traces[traceIds[i]];
    }

    //Update ranges (needs to be called *after* objects are added due to updates)
    var sceneBounds = this.glplot.bounds,
        axisDataRange = [];

    for(i = 0; i < 3; ++i) {
        var axis = fullSceneLayout[axisProperties[i]];

        if(axis.autorange) {
            sceneBounds[0][i] = Infinity;
            sceneBounds[1][i] = -Infinity;
            for(j = 0; j < this.glplot.objects.length; ++j) {
                var objBounds = this.glplot.objects[j].bounds;
                sceneBounds[0][i] = Math.min(sceneBounds[0][i], objBounds[0][i]);
                sceneBounds[1][i] = Math.max(sceneBounds[1][i], objBounds[1][i]);
            }
            if('rangemode' in axis && axis.rangemode === 'tozero') {
                sceneBounds[0][i] = Math.min(sceneBounds[0][i], 0);
                sceneBounds[1][i] = Math.max(sceneBounds[1][i], 0);
            }
            if(sceneBounds[0][i] > sceneBounds[1][i]) {
                sceneBounds[0][i] = -1;
                sceneBounds[1][i] =  1;
            } else {
                var d = sceneBounds[1][i] - sceneBounds[0][i];
                sceneBounds[0][i] -= d/32.0;
                sceneBounds[1][i] += d/32.0;
            }
        } else {
            var range = fullSceneLayout[axisProperties[i]].range;
            sceneBounds[0][i] = range[0];
            sceneBounds[1][i] = range[1];
        }
        if(sceneBounds[0][i] === sceneBounds[1][i]) {
            sceneBounds[0][i] -= 1;
            sceneBounds[1][i] += 1;
        }
        axisDataRange[i] = sceneBounds[1][i] - sceneBounds[0][i];
    }

    var axesScaleRatio = [],
        maxRange = Math.max.apply(null, axisDataRange);

    for (i = 0; i < 3; ++i) axesScaleRatio[i] = axisDataRange[i] / maxRange;

    /*
     * Dynamically set the aspect ratio depending on the users aspect settings
     */
    var axisAutoScaleFactor = 4;
    var aspectRatio;

    if (fullSceneLayout.aspectmode === 'auto') {
        if (Math.max.apply(null, axesScaleRatio)/Math.min.apply(null, axesScaleRatio) <= axisAutoScaleFactor) {

            /*
             * USE DATA MODE WHEN AXIS RANGE DIMENSIONS ARE RELATIVELY EQUAL
             */
            aspectRatio = axesScaleRatio;
        } else {

            /*
             * USE EQUAL MODE WHEN AXIS RANGE DIMENSIONS ARE HIGHLY UNEQUAL
             */
            aspectRatio = [1, 1, 1];
        }

    } else if (fullSceneLayout.aspectmode === 'cube') {
        aspectRatio = [1, 1, 1];

    } else if (fullSceneLayout.aspectmode === 'data') {
        aspectRatio = axesScaleRatio;

    } else if (fullSceneLayout.aspectmode === 'manual') {
        var userRatio = fullSceneLayout.aspectratio;
        aspectRatio = [userRatio.x, userRatio.y, userRatio.z];

    } else {
        throw new Error('scene.js aspectRatio was not one of the enumerated types');
    }

    /*
     * Write aspect Ratio back to user data and fullLayout so that it is modifies as user
     * manipulates the aspectmode settings and the fullLayout is up-to-date.
     */
    fullSceneLayout.aspectratio.x = sceneLayout.aspectratio.x = aspectRatio[0];
    fullSceneLayout.aspectratio.y = sceneLayout.aspectratio.y = aspectRatio[1];
    fullSceneLayout.aspectratio.z = sceneLayout.aspectratio.z = aspectRatio[2];

    /*
     * Finally assign the computed aspecratio to the glplot module. This will have an effect
     * on the next render cycle.
     */
    this.glplot.aspect = aspectRatio;

    //Update frame position for multi plots
    var domain = fullSceneLayout.domain || null,
        size = fullLayout._size || null;

    if (domain && size) {
        var containerStyle = this.container.style;
        containerStyle.position = 'absolute';
        containerStyle.left     = (size.l + domain.x[0] * size.w) + 'px';
        containerStyle.top      = (size.t + (1 - domain.y[1]) * size.h) + 'px';
        containerStyle.width    = (size.w * (domain.x[1] - domain.x[0])) + 'px';
        containerStyle.height   = (size.h * (domain.y[1] - domain.y[0])) + 'px';
    }
};

proto.destroy = function() {
    this.glplot.dispose();
    this.container.parentNode.removeChild(this.container);
};

// for reset camera button in modebar
proto.setCameraToDefault = function setCameraToDefault () {
    // as in Gl3dLayout.layoutAttributes
    this.glplot.camera.lookAt(
        [1.25, 1.25, 1.25],
        [0   , 0   , 0   ],
        [0   , 0   , 1   ]
    );
};

// get camera position in plotly coords from 'orbit-camera' coords
proto.getCameraPosition = function getCameraPosition () {
    this.glplot.camera.view.recalcMatrix(this.camera.view.lastT());

    var up     = this.glplot.camera.up;
    var center = this.glplot.camera.center;
    var eye    = this.glplot.camera.eye;

    return {
        up:     {x:up[0], y:up[1], z:up[2]},
        center: {x:center[0], y:center[1], z:center[2]},
        eye:    {x:eye[0], y:eye[1], z:eye[2]}
    };
};

// set camera position with a set of plotly coords
proto.setCameraPosition = function setCameraPosition (cameraPos) {
    var up      = cameraPos.up;
    var center  = cameraPos.center;
    var eye     = cameraPos.eye;
    this.glplot.camera.lookAt(
        [eye.x, eye.y, eye.z],
        [center.x, center.y, center.z],
        [up.x, up.y, up.z]
    );
};

// save camera to user layout (i.e. gd.layout)
proto.saveCamera = function saveCamera(layout) {
    var cameraposition = this.getCameraPosition();

    // save new camera api
    Plotly.Lib.nestedProperty(layout, this.id + '.camera')
        .set(cameraposition);

    // delete old
    delete layout.scene.cameraposition;
};

// convert old camera position api
proto.cleanCamera = function(cameraposition) {
    if (Array.isArray(cameraposition) && cameraposition[0].length === 4) {
        var rotation = cameraposition[0];
        var center   = cameraposition[1];
        var radius   = cameraposition[2];
        var mat = m4FromQuat([], rotation);
        var eye = [];
        for (var i = 0; i < 3; ++i) {
            eye[i] = center[i] + radius * mat[2+4*i];
        }
        return {
            eye: {x: eye[0], y: eye[1], z: eye[2]},
            center: {x: center[0], y: center[1], z: center[2]},
            up: {x: mat[1], y: mat[5], z: mat[9]}
        };
    }
    else return null;
};

proto.toImage = function (format) {
    if (!format) format = 'png';

    var gl = this.glplot.gl;
    var w = gl.drawingBufferWidth;
    var h = gl.drawingBufferHeight;

    gl.bindFramebuffer(gl.FRAMEBUFFER, null);

    var pixels = new Uint8Array(w * h * 4);
    gl.readPixels(0, 0, w, h, gl.RGBA, gl.UNSIGNED_BYTE, pixels);

    //Flip pixels
    for(var j=0,k=h-1; j<k; ++j, --k) {
        for(var i=0; i<w; ++i) {
            for(var l=0; l<4; ++l) {
                var tmp = pixels[4*(w*j+i)+l];
                pixels[4*(w*j+i)+l] = pixels[4*(w*k+i)+l];
                pixels[4*(w*k+i)+l] = tmp;
            }
        }
    }

    var canvas = document.createElement('canvas');
    canvas.width = w;
    canvas.height = h;
    var context = canvas.getContext('2d');
    var imageData = context.createImageData(w, h);
    imageData.data.set(pixels);
    context.putImageData(imageData, 0, 0);

    var dataURL;

    switch (format) {
        case 'jpeg':
            dataURL = canvas.toDataURL('image/jpeg');
            break;
        case 'webp':
            dataURL = canvas.toDataURL('image/webp');
            break;
        default:
        dataURL = canvas.toDataURL('image/png');
    }

    return dataURL;
};

module.exports = Scene;
<|endoftext|>


<commit_before>"use strict";
(function(window) {
    function Moon(opts) {
        var _el = opts.el;
        var _data = opts.data;
        var _methods = opts.methods;
        var directives = {};
        var self = this;
        this.$el = document.querySelector(_el);
        this.components = opts.components;
        this.dom = {type: this.$el.nodeName, children: [], node: this.$el};

        // Change state when $data is changed
        Object.defineProperty(this, '$data', {
            get: function() {
                return _data;
            },
            set: function(value) {
                _data = value;
                this.build(this.dom.children);
            }
        });

        /**
        * Converts attributes into key-value pairs
        * @param {Node} node
        * @return {Object} Key-Value pairs of Attributes
        */
        var extractAttrs = function(node) {
          var attrs = {};
          if(!node.attributes) return attrs;
          var rawAttrs = node.attributes;
          for(var i = 0; i < rawAttrs.length; i++) {
            attrs[rawAttrs[i].name] = rawAttrs[i].value
          }

          return attrs;
        }

        // Utility: Compile a template and return html
        var compileTemplate = function(template, data) {
          var code = template,
              re = /{{([.]?\w+)}}/gi;
          code.replace(re, function(match, p) {
            code = code.replace(match, "` + data." + p + " + `");
          });
          var compile = new Function("data", "var out = `" + code + "`; return out");
          return compile(data);
        }

        // Create Virtual DOM Object from Params
        this.createElement = function(type, children, val, props, node) {
          return {type: type, children: children, val: val, props: props, node: node};
        }

        // Utility: Create Elements Recursively For all Children
        this.recursiveChildren = function(children) {
          var recursiveChildrenArr = [];
          for(var i = 0; i < children.length; i++) {
            var child = children[i];
            recursiveChildrenArr.push(this.createElement(child.nodeName, this.recursiveChildren(child.childNodes), child.textContent, extractAttrs(child), child));
          }
          return recursiveChildrenArr;
        }

        // Utility: Create Virtual DOM Instance
        this.createVirtualDOM = function(node) {
          var vdom = this.createElement(node.nodeName, this.recursiveChildren(node.childNodes), node.textContent, extractAttrs(node), node);
          this.dom = vdom;
        }

        //
        this.componentsToHTML = function() {
          for(var component in this.components) {
            var componentsFound = document.getElementsByTagName(component);
            for(var i = 0; i < componentsFound.length; i++) {
              componentsFound[i].outerHTML = this.components[component].template;
            }
          }
        }

        // Set any value in $data
        this.set = function(key, val) {
          this.$data[key] = val;
          this.build(this.dom.children);
        }

        // Get any value in $data
        this.get = function(key) {
          return this.$data[key];
        }

        // Make AJAX GET/POST requests
        this.ajax = function(method, url, params, cb) {
          var xmlHttp = new XMLHttpRequest();
          method = method.toUpperCase();
          if(typeof params === "function") {
            cb = params;
          }
          var urlParams = "?";
          if(method === "POST") {
            http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            for(var param in params) {
              urlParams += param + "=" + params[param] + "&";
            }
          }
          xmlHttp.onreadystatechange = function() {
          if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
            cb(JSON.parse(xmlHttp.responseText));
          }
          xmlHttp.open(method, url, true);
          xmlHttp.send(method === "POST" ? urlParams : null);
        }

        // Call a method defined in _methods
        this.method = function(method) {
          _methods[method]();
        }

        // Directive Initialization
        this.directive = function(name, action) {
          directives["m-" + name] = action;
        }

        // Default Directives
        directives["m-if"] = function(el, val, vdom) {
          var evaluated = new Function("return " + val);
          if(!evaluated()) {
            el.textContent = "";
          } else {
            el.textContent = compileTemplate(vdom.val, self.$data);
          }
        }

        // Build the DOM with $data
        this.build = function(children) {
          for(var i = 0; i < children.length; i++) {
            var el = children[i];

            if(el.type === "#text") {
              el.node.textContent = compileTemplate(el.val, this.$data);
            } else if(el.props) {
              for(var prop in el.props) {
                var propVal = el.props[prop];
                var compiledProperty = compileTemplate(propVal, this.$data);
                var directive = directives[prop];
                if(directive) {
                  directive(el.node, compiledProperty, el);
                }

                el.node.setAttribute(prop, compiledProperty);
              }
            }

            this.build(el.children);
          }
        }

        // Initialize
        this.componentsToHTML();
        this.createVirtualDOM(this.$el);
        this.build(this.dom.children);
    }

    window.Moon = Moon;
    window.$ = function(el) {
      el = document.querySelectorAll(el);
      return el.length === 1 ? el[0] : el;
    }

})(window);
<commit_msg>comment compile template<commit_after>"use strict";
(function(window) {
    function Moon(opts) {
        var _el = opts.el;
        var _data = opts.data;
        var _methods = opts.methods;
        var directives = {};
        var self = this;
        this.$el = document.querySelector(_el);
        this.components = opts.components;
        this.dom = {type: this.$el.nodeName, children: [], node: this.$el};

        // Change state when $data is changed
        Object.defineProperty(this, '$data', {
            get: function() {
                return _data;
            },
            set: function(value) {
                _data = value;
                this.build(this.dom.children);
            }
        });

        /**
        * Converts attributes into key-value pairs
        * @param {Node} node
        * @return {Object} Key-Value pairs of Attributes
        */
        var extractAttrs = function(node) {
          var attrs = {};
          if(!node.attributes) return attrs;
          var rawAttrs = node.attributes;
          for(var i = 0; i < rawAttrs.length; i++) {
            attrs[rawAttrs[i].name] = rawAttrs[i].value
          }

          return attrs;
        }

        /**
        * Compiles a template with given data
        * @param {String} template
        * @param {Object} data
        * @return {String} Template with data rendered
        */
        var compileTemplate = function(template, data) {
          var code = template,
              re = /{{([.]?\w+)}}/gi;
          code.replace(re, function(match, p) {
            code = code.replace(match, "` + data." + p + " + `");
          });
          var compile = new Function("data", "var out = `" + code + "`; return out");
          return compile(data);
        }

        // Create Virtual DOM Object from Params
        this.createElement = function(type, children, val, props, node) {
          return {type: type, children: children, val: val, props: props, node: node};
        }

        // Utility: Create Elements Recursively For all Children
        this.recursiveChildren = function(children) {
          var recursiveChildrenArr = [];
          for(var i = 0; i < children.length; i++) {
            var child = children[i];
            recursiveChildrenArr.push(this.createElement(child.nodeName, this.recursiveChildren(child.childNodes), child.textContent, extractAttrs(child), child));
          }
          return recursiveChildrenArr;
        }

        // Utility: Create Virtual DOM Instance
        this.createVirtualDOM = function(node) {
          var vdom = this.createElement(node.nodeName, this.recursiveChildren(node.childNodes), node.textContent, extractAttrs(node), node);
          this.dom = vdom;
        }

        //
        this.componentsToHTML = function() {
          for(var component in this.components) {
            var componentsFound = document.getElementsByTagName(component);
            for(var i = 0; i < componentsFound.length; i++) {
              componentsFound[i].outerHTML = this.components[component].template;
            }
          }
        }

        // Set any value in $data
        this.set = function(key, val) {
          this.$data[key] = val;
          this.build(this.dom.children);
        }

        // Get any value in $data
        this.get = function(key) {
          return this.$data[key];
        }

        // Make AJAX GET/POST requests
        this.ajax = function(method, url, params, cb) {
          var xmlHttp = new XMLHttpRequest();
          method = method.toUpperCase();
          if(typeof params === "function") {
            cb = params;
          }
          var urlParams = "?";
          if(method === "POST") {
            http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            for(var param in params) {
              urlParams += param + "=" + params[param] + "&";
            }
          }
          xmlHttp.onreadystatechange = function() {
          if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
            cb(JSON.parse(xmlHttp.responseText));
          }
          xmlHttp.open(method, url, true);
          xmlHttp.send(method === "POST" ? urlParams : null);
        }

        // Call a method defined in _methods
        this.method = function(method) {
          _methods[method]();
        }

        // Directive Initialization
        this.directive = function(name, action) {
          directives["m-" + name] = action;
        }

        // Default Directives
        directives["m-if"] = function(el, val, vdom) {
          var evaluated = new Function("return " + val);
          if(!evaluated()) {
            el.textContent = "";
          } else {
            el.textContent = compileTemplate(vdom.val, self.$data);
          }
        }

        // Build the DOM with $data
        this.build = function(children) {
          for(var i = 0; i < children.length; i++) {
            var el = children[i];

            if(el.type === "#text") {
              el.node.textContent = compileTemplate(el.val, this.$data);
            } else if(el.props) {
              for(var prop in el.props) {
                var propVal = el.props[prop];
                var compiledProperty = compileTemplate(propVal, this.$data);
                var directive = directives[prop];
                if(directive) {
                  directive(el.node, compiledProperty, el);
                }

                el.node.setAttribute(prop, compiledProperty);
              }
            }

            this.build(el.children);
          }
        }

        // Initialize
        this.componentsToHTML();
        this.createVirtualDOM(this.$el);
        this.build(this.dom.children);
    }

    window.Moon = Moon;
    window.$ = function(el) {
      el = document.querySelectorAll(el);
      return el.length === 1 ? el[0] : el;
    }

})(window);
<|endoftext|>