all files / src/visualizations/deckgl/layers/ screengrid.jsx

40% Statements 26/65
19.35% Branches 6/31
6.67% Functions 1/15
38.18% Lines 21/55
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148                                                                                                                                                                                                                                                              
EI/* eslint no-underscore-dangle: ["error", { "allow": ["", "__timestamp"] }] */
 
import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
 
import { ScreenGridLayer } from 'deck.gl';
 
import AnimatableDeckGLContainer from '../AnimatableDeckGLContainer';
 
import * as common from './common';
import { getPlaySliderParams } from '../../../modules/time';
import sandboxedEval from '../../../modules/sandbox';
 
function getPoints(data) {
  return data.map(d => d.position);
}
 
function getLayer(formData, payload, slice, filters) {
  const fd = formData;
  const c = fd.color_picker;
  let data = payload.data.features.map(d => ({
    ...d,
    color: [c.r, c.g, c.b, 255 * c.a],
  }));
 
  if (fd.js_data_mutator) {
    // Applying user defined data mutator if defined
    const jsFnMutator = sandboxedEval(fd.js_data_mutator);
    data = jsFnMutator(data);
  }
 
  if (filters != null) {
    filters.forEach((f) => {
      data = data.filter(f);
    });
  }
 
  // Passing a layer creator function instead of a layer since the
  // layer needs to be regenerated at each render
  return new ScreenGridLayer({
    id: `screengrid-layer-${fd.slice_id}`,
    data,
    pickable: true,
    cellSizePixels: fd.grid_size,
    minColor: [c.r, c.g, c.b, 0],
    maxColor: [c.r, c.g, c.b, 255 * c.a],
    outline: false,
    getWeight: d => d.weight || 0,
    ...common.commonLayerProps(fd, slice),
  });
}
 
const propTypes = {
  slice: PropTypes.object.isRequired,
  payload: PropTypes.object.isRequired,
  setControlValue: PropTypes.func.isRequired,
  viewport: PropTypes.object.isRequired,
};
 
class DeckGLScreenGrid extends React.PureComponent {
  /* eslint-disable no-unused-vars */
  static getDerivedStateFromProps(nextProps, prevState) {
    const fd = nextProps.slice.formData;
 
    const timeGrain = fd.time_grain_sqla || fd.granularity || 'PT1M';
    const timestamps = nextProps.payload.data.features.map(f => f.__timestamp);
    const { start, end, step, values, disabled } = getPlaySliderParams(timestamps, timeGrain);
 
    return { start, end, step, values, disabled };
  }
  constructor(props) {
    super(props);
    this.state = DeckGLScreenGrid.getDerivedStateFromProps(props);
 
    this.getLayers = this.getLayers.bind(this);
  }
  componentWillReceiveProps(nextProps) {
    this.setState(DeckGLScreenGrid.getDerivedStateFromProps(nextProps, this.state));
  }
  getLayers(values) {
    const filters = [];
 
    // time filter
    if (values[0] === values[1] || values[1] === this.end) {
      filters.push(d => d.__timestamp >= values[0] && d.__timestamp <= values[1]);
    } else {
      filters.push(d => d.__timestamp >= values[0] && d.__timestamp < values[1]);
    }
 
    const layer = getLayer(
      this.props.slice.formData,
      this.props.payload,
      this.props.slice,
      filters);
 
    return [layer];
  }
  render() {
    return (
      <div>
        <AnimatableDeckGLContainer
          getLayers={this.getLayers}
          start={this.state.start}
          end={this.state.end}
          step={this.state.step}
          values={this.state.values}
          disabled={this.state.disabled}
          viewport={this.props.viewport}
          mapboxApiAccessToken={this.props.payload.data.mapboxApiKey}
          mapStyle={this.props.slice.formData.mapbox_style}
          setControlValue={this.props.setControlValue}
        />
      </div>
    );
  }
}
 
DeckGLScreenGrid.propTypes = propTypes;
 
function deckScreenGrid(slice, payload, setControlValue) {
  const fd = slice.formData;
  let viewport = {
    ...fd.viewport,
    width: slice.width(),
    height: slice.height(),
  };
 
  if (fd.autozoom) {
    viewport = common.fitViewport(viewport, getPoints(payload.data.features));
  }
 
  ReactDOM.render(
    <DeckGLScreenGrid
      slice={slice}
      payload={payload}
      setControlValue={setControlValue}
      viewport={viewport}
    />,
    document.getElementById(slice.containerId),
  );
}
 
module.exports = {
  default: deckScreenGrid,
  getLayer,
};