<commit_before>/**
 * Copyright (c) 2015-present, Pavel Aksonov
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree.
 *
 */
import React, {
  Component,
  PropTypes,
} from 'react';
import {
  Animated,
  View,
  StyleSheet,
} from 'react-native';

import TabBar from './TabBar';
import NavBar from './NavBar';
import Actions from './Actions';
import { deepestExplicitValueForKey } from './Util';
import NavigationExperimental from 'react-native-experimental-navigation';
import PureRenderMixin from 'react-addons-pure-render-mixin';

const {
  AnimatedView: NavigationAnimatedView,
  Card: NavigationCard,
} = NavigationExperimental;

const {
  CardStackPanResponder: NavigationCardStackPanResponder,
  CardStackStyleInterpolator: NavigationCardStackStyleInterpolator,
} = NavigationCard;

const styles = StyleSheet.create({
  animatedView: {
    flex: 1,
    backgroundColor: 'transparent',
  },
  sceneStyle: {
    flex: 1,
  },
});

function fadeInScene(/* NavigationSceneRendererProps */ props) {
  const {
    position,
    scene,
  } = props;

  const index = scene.index;
  const inputRange = [index - 1, index, index + 1];

  const opacity = position.interpolate({
    inputRange,
    outputRange: [0, 1, 0.3],
  });

  const scale = position.interpolate({
    inputRange,
    outputRange: [1, 1, 0.95],
  });

  const translateY = 0;
  const translateX = 0;

  return {
    opacity,
    transform: [
      { scale },
      { translateX },
      { translateY },
    ],
  };
}

export default class DefaultRenderer extends Component {

  static propTypes = {
    navigationState: PropTypes.object,
    onNavigate: PropTypes.func,
  };

  static childContextTypes = {
    navigationState: PropTypes.any,
  };

  constructor(props) {
    super(props);

    this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
    this.renderCard = this.renderCard.bind(this);
    this.renderScene = this.renderScene.bind(this);
    this.renderHeader = this.renderHeader.bind(this);
  }

  getChildContext() {
    return {
      navigationState: this.props.navigationState,
    };
  }

  componentDidMount() {
    this.dispatchFocusAction(this.props);
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.navigationState !== this.props.navigationState) {
      this.dispatchFocusAction(nextProps);
    }
  }

  getPanHandlers(direction, props) {
    return direction === 'vertical' ?
      NavigationCardStackPanResponder.forVertical(props) :
      NavigationCardStackPanResponder.forHorizontal(props);
  }

  dispatchFocusAction({ navigationState }) {
    if (!navigationState || navigationState.component || navigationState.tabs) {
      return;
    }
    const scene = navigationState.children[navigationState.index];
    Actions.focus({ scene });
  }

  chooseInterpolator(direction, props) {
    switch (direction) {
      case 'vertical':
        return NavigationCardStackStyleInterpolator.forVertical(props);
      case 'fade':
        return fadeInScene(props);
      default:
        return NavigationCardStackStyleInterpolator.forHorizontal(props);
    }
  }

  renderCard(/* NavigationSceneRendererProps */ props) {
    const { key,
      direction,
      animation,
      getSceneStyle,
      getPanHandlers,
    } = props.scene.navigationState;
    let { panHandlers, animationStyle } = props.scene.navigationState;

    const state = props.navigationState;
    const child = state.children[state.index];
    let selected = state.children[state.index];
    while (selected.hasOwnProperty('children')) {
      selected = selected.children[selected.index];
    }
    const isActive = child === selected;
    const computedProps = { isActive };
    if (isActive) {
      computedProps.hideNavBar = deepestExplicitValueForKey(props.navigationState, 'hideNavBar');
      computedProps.hideTabBar = deepestExplicitValueForKey(props.navigationState, 'hideTabBar');
    }

    const style = getSceneStyle ? getSceneStyle(props, computedProps) : null;

    // direction overrides animation if both are supplied
    const animType = (animation && !direction) ? animation : direction;

    if (typeof(animationStyle) === 'undefined') {
      animationStyle = this.chooseInterpolator(animType, props);
    }

    if (typeof(animationStyle) === 'function') {
      animationStyle = animationStyle(props);
    }

    if (typeof(panHandlers) === 'undefined') {
      panHandlers = getPanHandlers ? getPanHandlers(props) : this.getPanHandlers(direction, props);
    }
    return (
      <NavigationCard
        {...props}
        key={`card_${key}`}
        style={[animationStyle, style]}
        panHandlers={panHandlers}
        renderScene={this.renderScene}
      />
    );
  }

  renderScene(/* NavigationSceneRendererProps */ props) {
    return (
      <DefaultRenderer
        key={props.scene.navigationState.key}
        onNavigate={props.onNavigate}
        navigationState={props.scene.navigationState}
      />
    );
  }

  renderHeader(/* NavigationSceneRendererProps */ props) {
    const state = props.navigationState;
    const child = state.children[state.index];
    let selected = state.children[state.index];
    while (selected.hasOwnProperty('children')) {
      selected = selected.children[selected.index];
    }
    if (child !== selected) {
      // console.log(`SKIPPING renderHeader because ${child.key} !== ${selected.key}`);
      return null;
    }
    const hideNavBar = deepestExplicitValueForKey(state, 'hideNavBar');
    if (hideNavBar) {
      // console.log(`SKIPPING renderHeader because ${child.key} hideNavBar === true`);
      return null;
    }

    // console.log(`renderHeader for ${child.key}`);

    if (selected.component && selected.component.renderNavigationBar) {
      return selected.component.renderNavigationBar({ ...props, ...selected });
    }

    const HeaderComponent = selected.navBar || child.navBar || state.navBar || NavBar;
    const navBarProps = { ...state, ...child, ...selected };

    if (selected.component && selected.component.onRight) {
      navBarProps.onRight = selected.component.onRight;
    }

    if (selected.component && selected.component.onLeft) {
      navBarProps.onLeft = selected.component.onLeft;
    }

    if ((navBarProps.leftTitle || navBarProps.leftButtonImage) && navBarProps.onLeft) {
      delete navBarProps.leftButton;
    }

    if ((navBarProps.rightTitle || navBarProps.rightButtonImage) && navBarProps.onRight) {
      delete navBarProps.rightButton;
    }

    if (navBarProps.rightButton) {
      delete navBarProps.rightTitle;
      delete navBarProps.onRight;
      delete navBarProps.rightButtonImage;
    }

    if (navBarProps.leftButton) {
      delete navBarProps.leftTitle;
      delete navBarProps.onLeft;
      delete navBarProps.leftButtonImage;
    }
    delete navBarProps.style;

    const getTitle = selected.getTitle || (opts => opts.title);
    return <HeaderComponent {...props} {...navBarProps} getTitle={getTitle} />;
  }

  render() {
    const { navigationState, onNavigate } = this.props;

    if (!navigationState || !onNavigate) {
      console.error('navigationState and onNavigate property should be not null');
      return null;
    }

    let SceneComponent = navigationState.component;

    if (navigationState.tabs && !SceneComponent) {
      SceneComponent = TabBar;
    }

    if (SceneComponent) {
      return (
        <View
          style={[styles.sceneStyle, navigationState.sceneStyle]}
        >
          <SceneComponent {...this.props} {...navigationState} />
        </View>
      );
    }

    const optionals = {};
    const selected = navigationState.children[navigationState.index];
    const applyAnimation = selected.applyAnimation || navigationState.applyAnimation;
    const style = selected.style || navigationState.style;

    if (applyAnimation) {
      optionals.applyAnimation = applyAnimation;
    } else {
      let duration = selected.duration;
      if (duration === null || duration === undefined) duration = navigationState.duration;
      if (duration !== null && duration !== undefined) {
        optionals.applyAnimation = (pos, navState) => {
          if (duration === 0) {
            pos.setValue(navState.index);
          } else {
            Animated.timing(pos, { toValue: navState.index, duration }).start();
          }
        };
      }
    }

    // console.log(`NavigationAnimatedView for ${navigationState.key}`);

    return (
      <NavigationAnimatedView
        navigationState={navigationState}
        style={[styles.animatedView, style]}
        renderOverlay={this.renderHeader}
        renderScene={this.renderCard}
        {...optionals}
      />
    );
  }
}
<commit_msg>Add 'leftToRight' direction support (#1032)<commit_after>/**
 * Copyright (c) 2015-present, Pavel Aksonov
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree.
 *
 */
import React, {
  Component,
  PropTypes,
} from 'react';
import {
  Animated,
  View,
  StyleSheet,
  Dimensions,
} from 'react-native';

import TabBar from './TabBar';
import NavBar from './NavBar';
import Actions from './Actions';
import { deepestExplicitValueForKey } from './Util';
import NavigationExperimental from 'react-native-experimental-navigation';
import PureRenderMixin from 'react-addons-pure-render-mixin';

const SCREEN_WIDTH = Dimensions.get('window').width;

const {
  AnimatedView: NavigationAnimatedView,
  Card: NavigationCard,
} = NavigationExperimental;

const {
  CardStackPanResponder: NavigationCardStackPanResponder,
  CardStackStyleInterpolator: NavigationCardStackStyleInterpolator,
} = NavigationCard;

const styles = StyleSheet.create({
  animatedView: {
    flex: 1,
    backgroundColor: 'transparent',
  },
  sceneStyle: {
    flex: 1,
  },
});

function fadeInScene(/* NavigationSceneRendererProps */ props) {
  const {
    position,
    scene,
  } = props;

  const index = scene.index;
  const inputRange = [index - 1, index, index + 1];

  const opacity = position.interpolate({
    inputRange,
    outputRange: [0, 1, 0.3],
  });

  const scale = position.interpolate({
    inputRange,
    outputRange: [1, 1, 0.95],
  });

  const translateY = 0;
  const translateX = 0;

  return {
    opacity,
    transform: [
      { scale },
      { translateX },
      { translateY },
    ],
  };
}

function leftToRight(/* NavigationSceneRendererProps */ props) {
  const {
    position,
    scene,
  } = props;

  const index = scene.index;
  const inputRange = [index - 1, index, index + 1];

  const translateX = position.interpolate({
    inputRange,
    outputRange: [-SCREEN_WIDTH, 0, 0],
  });

  return {
    transform: [
      { translateX },
    ],
  };
}

export default class DefaultRenderer extends Component {

  static propTypes = {
    navigationState: PropTypes.object,
    onNavigate: PropTypes.func,
  };

  static childContextTypes = {
    navigationState: PropTypes.any,
  };

  constructor(props) {
    super(props);

    this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
    this.renderCard = this.renderCard.bind(this);
    this.renderScene = this.renderScene.bind(this);
    this.renderHeader = this.renderHeader.bind(this);
  }

  getChildContext() {
    return {
      navigationState: this.props.navigationState,
    };
  }

  componentDidMount() {
    this.dispatchFocusAction(this.props);
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.navigationState !== this.props.navigationState) {
      this.dispatchFocusAction(nextProps);
    }
  }

  getPanHandlers(direction, props) {
    return direction === 'vertical' ?
      NavigationCardStackPanResponder.forVertical(props) :
      NavigationCardStackPanResponder.forHorizontal(props);
  }

  dispatchFocusAction({ navigationState }) {
    if (!navigationState || navigationState.component || navigationState.tabs) {
      return;
    }
    const scene = navigationState.children[navigationState.index];
    Actions.focus({ scene });
  }

  chooseInterpolator(direction, props) {
    switch (direction) {
      case 'vertical':
        return NavigationCardStackStyleInterpolator.forVertical(props);
      case 'fade':
        return fadeInScene(props);
      case 'leftToRight':
        return leftToRight(props);
      default:
        return NavigationCardStackStyleInterpolator.forHorizontal(props);
    }
  }

  renderCard(/* NavigationSceneRendererProps */ props) {
    const { key,
      direction,
      animation,
      getSceneStyle,
      getPanHandlers,
    } = props.scene.navigationState;
    let { panHandlers, animationStyle } = props.scene.navigationState;

    const state = props.navigationState;
    const child = state.children[state.index];
    let selected = state.children[state.index];
    while (selected.hasOwnProperty('children')) {
      selected = selected.children[selected.index];
    }
    const isActive = child === selected;
    const computedProps = { isActive };
    if (isActive) {
      computedProps.hideNavBar = deepestExplicitValueForKey(props.navigationState, 'hideNavBar');
      computedProps.hideTabBar = deepestExplicitValueForKey(props.navigationState, 'hideTabBar');
    }

    const style = getSceneStyle ? getSceneStyle(props, computedProps) : null;

    // direction overrides animation if both are supplied
    const animType = (animation && !direction) ? animation : direction;

    if (typeof(animationStyle) === 'undefined') {
      animationStyle = this.chooseInterpolator(animType, props);
    }

    if (typeof(animationStyle) === 'function') {
      animationStyle = animationStyle(props);
    }

    if (typeof(panHandlers) === 'undefined') {
      panHandlers = getPanHandlers ? getPanHandlers(props) : this.getPanHandlers(direction, props);
    }
    return (
      <NavigationCard
        {...props}
        key={`card_${key}`}
        style={[animationStyle, style]}
        panHandlers={panHandlers}
        renderScene={this.renderScene}
      />
    );
  }

  renderScene(/* NavigationSceneRendererProps */ props) {
    return (
      <DefaultRenderer
        key={props.scene.navigationState.key}
        onNavigate={props.onNavigate}
        navigationState={props.scene.navigationState}
      />
    );
  }

  renderHeader(/* NavigationSceneRendererProps */ props) {
    const state = props.navigationState;
    const child = state.children[state.index];
    let selected = state.children[state.index];
    while (selected.hasOwnProperty('children')) {
      selected = selected.children[selected.index];
    }
    if (child !== selected) {
      // console.log(`SKIPPING renderHeader because ${child.key} !== ${selected.key}`);
      return null;
    }
    const hideNavBar = deepestExplicitValueForKey(state, 'hideNavBar');
    if (hideNavBar) {
      // console.log(`SKIPPING renderHeader because ${child.key} hideNavBar === true`);
      return null;
    }

    // console.log(`renderHeader for ${child.key}`);

    if (selected.component && selected.component.renderNavigationBar) {
      return selected.component.renderNavigationBar({ ...props, ...selected });
    }

    const HeaderComponent = selected.navBar || child.navBar || state.navBar || NavBar;
    const navBarProps = { ...state, ...child, ...selected };

    if (selected.component && selected.component.onRight) {
      navBarProps.onRight = selected.component.onRight;
    }

    if (selected.component && selected.component.onLeft) {
      navBarProps.onLeft = selected.component.onLeft;
    }

    if ((navBarProps.leftTitle || navBarProps.leftButtonImage) && navBarProps.onLeft) {
      delete navBarProps.leftButton;
    }

    if ((navBarProps.rightTitle || navBarProps.rightButtonImage) && navBarProps.onRight) {
      delete navBarProps.rightButton;
    }

    if (navBarProps.rightButton) {
      delete navBarProps.rightTitle;
      delete navBarProps.onRight;
      delete navBarProps.rightButtonImage;
    }

    if (navBarProps.leftButton) {
      delete navBarProps.leftTitle;
      delete navBarProps.onLeft;
      delete navBarProps.leftButtonImage;
    }
    delete navBarProps.style;

    const getTitle = selected.getTitle || (opts => opts.title);
    return <HeaderComponent {...props} {...navBarProps} getTitle={getTitle} />;
  }

  render() {
    const { navigationState, onNavigate } = this.props;

    if (!navigationState || !onNavigate) {
      console.error('navigationState and onNavigate property should be not null');
      return null;
    }

    let SceneComponent = navigationState.component;

    if (navigationState.tabs && !SceneComponent) {
      SceneComponent = TabBar;
    }

    if (SceneComponent) {
      return (
        <View
          style={[styles.sceneStyle, navigationState.sceneStyle]}
        >
          <SceneComponent {...this.props} {...navigationState} />
        </View>
      );
    }

    const optionals = {};
    const selected = navigationState.children[navigationState.index];
    const applyAnimation = selected.applyAnimation || navigationState.applyAnimation;
    const style = selected.style || navigationState.style;

    if (applyAnimation) {
      optionals.applyAnimation = applyAnimation;
    } else {
      let duration = selected.duration;
      if (duration === null || duration === undefined) duration = navigationState.duration;
      if (duration !== null && duration !== undefined) {
        optionals.applyAnimation = (pos, navState) => {
          if (duration === 0) {
            pos.setValue(navState.index);
          } else {
            Animated.timing(pos, { toValue: navState.index, duration }).start();
          }
        };
      }
    }

    // console.log(`NavigationAnimatedView for ${navigationState.key}`);

    return (
      <NavigationAnimatedView
        navigationState={navigationState}
        style={[styles.animatedView, style]}
        renderOverlay={this.renderHeader}
        renderScene={this.renderCard}
        {...optionals}
      />
    );
  }
}
<|endoftext|>


<commit_before>// @flow

export default {
	path: 'areas(/:type)(/:name)(/:revision)',

	getComponents(location: mixed, cb: Function) {
		import(/* webpackChunkName: 'area-editor.components' */ '../../modules/area-editor').then(
			mod => cb(null, {content: mod.default}),
		)
	},
}
<commit_msg>import the new area editor into gobbldygook<commit_after>// @flow

export default {
	path: 'areas(/:type)(/:name)(/:revision)',

	getComponents(location: mixed, cb: Function) {
		import(/* webpackChunkName: 'area-editor.components' */ '@gob/area-editor').then(
			mod => cb(null, {content: mod.Editor}),
		)
	},
}
<|endoftext|>


<commit_before>import React from 'react';
import {render} from 'react-dom';
import 'aframe';
import VirtualShowRoom from './VirtualShowRoom';

let config = {
    ...require('../config.json'),
    show: true,
    showOnlyProduct: false,
};

window.VirtualShowRoom = {
    show: () => doRender({...config, show: true}),
    hide: () => doRender({...config, show: false}),
    showOnlyProduct: () => doRender({...config, showOnlyProduct})
}

console.info('config', config);

const doRender = config => render(<VirtualShowRoom config={config}/>, document.querySelector('#root'));

document.addEventListener('DOMContentLoaded', () => doRender(config));
<commit_msg>show / hide the scene<commit_after>import React from 'react';
import {render} from 'react-dom';
import 'aframe';
import VirtualShowRoom from './VirtualShowRoom';

let config = {
    ...require('../config.json'),
    show: true,
    showOnlyProduct: false,
};

window.VirtualShowRoom = {
    show: () => doRender({...config, show: true}),
    hide: () => doRender({...config, show: false}),
    showOnlyProduct: () => doRender({...config, showOnlyProduct: true}),
    showAll: () => doRender({...config, showOnlyProduct: false})
}

console.info('config', config);

const doRender = config => render(<VirtualShowRoom config={config}/>, document.querySelector('#root'));

document.addEventListener('DOMContentLoaded', () => doRender(config));
<|endoftext|>


<commit_before>import _ from 'lodash'
import d3 from 'd3'
import React from 'react'
import Layer from 'react-layer'

import color from 'util/color'
import palettes from 'util/palettes'
import Tooltip from 'component/Tooltip.jsx'

function _domain (data, options) {
  return [0, _(data).map(options.value).sum()]
}

var DEFAULTS = {
  domain: _domain,
  innerRadius: 0,
  outerRadius: 1,
  margin: {
    top: 0,
    right: 0,
    bottom: 0,
    left: 0
  },
  value: _.property('value'),
  color: palettes.blue,
  name: _.property('indicator.short_name'),
  yFormat: function (d) {
    return d3.format((Math.abs(d) < 1) ? '%' : 'n')(d)
  }
}

function PieChart () {
}

_.extend(PieChart.prototype, {
  defaults: DEFAULTS,

  initialize: function (el, data, options) {
    var opts = this._options = _.defaults({}, options, DEFAULTS)

    this._height = this._width = _.get(opts, 'size', el.clientWidth)

    var svg = this._svg = d3.select(el).append('svg').attr('class', 'pie')

    var g = svg.append('g').attr('class', 'margin')

    g
      .append('g').attr('class', 'data')
      .append('path').attr('class', 'bg')

    g.append('g').attr('class', 'annotation')

    this.update(data)
  },

  update: function (values, options) {
    options = _.assign(this._options, options)
    var margin = options.margin

    values = _(values)
      .filter(d => {
        var v = options.value(d)
        return _.isFinite(v) && v > 0
      })
      .sortBy(options.value)
      .reverse()
      .value()

    let data = []
    if (values.length === 1) {
      // assume single indicator respresenting perentage
      data.push({ value: Math.round(values[0].value * 100) / 100 })
      data.push({ value: 1 - data[0].value })
    } else {
      data = values
    }

    var w = this._width - margin.left - margin.right
    var h = this._height - margin.top - margin.bottom
    var s = Math.min(w, h)

    var svg = this._svg

    svg.attr({
      'viewBox': '0 0 ' + this._width + ' ' + this._height
    })
      .select('.margin')
      .attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')')

    var xPosition = options.notInCenter ? w / 4 : w / 2
    var yPosition = options.notInCenter ? h / 3 : h / 2

    let g = svg.select('.data')
      .attr('transform', 'translate(' + xPosition + ', ' + yPosition + ')')

    if (options.percentage) {
      var annotation = svg.select('.annotation').selectAll('.percentage').data([options.percentage])
      annotation.enter().append('text')
      annotation.attr('class', 'percentage')
        .attr({'x': xPosition, 'y': yPosition, 'dy': 5})
        .style({
          'text-anchor': 'middle',
          'opacity': d => { return d === '0%' ? 0 : 1 }
        })
        .text(d => { return d })

      annotation.exit().remove()
    }

    var arc = d3.svg.arc()
      .innerRadius(s / 2 * options.innerRadius)
      .outerRadius(s / 2 * options.outerRadius)

    svg.select('.bg')
      .datum({
        startAngle: 0,
        endAngle: 2 * Math.PI
      })
      .attr('d', arc)

    var scale = d3.scale.linear()
      .domain(options.domain(data, options))
      .range([0, 2 * Math.PI])

    var pie = d3.layout.stack()
      .values(function (d) {
        return [d]
      })
      .x(options.name)
      .y(options.value)
      .out(function (d, y0, y) {
        d.startAngle = scale(y0)
        d.endAngle = scale(y0 + y)
      })

    let fill = color.map(data.map(options.name), options.color)

    var slice = g.selectAll('.slice').data(pie(_.cloneDeep(data)))

    slice.enter()
      .append('path')
      .attr('class', 'slice')

    slice.attr({
      'd': arc,
      'fill': _.flow(options.name, fill),
      'stroke': '#fff'
    }).on('mousemove', d => {
      var evt = d3.event
      var render = function () {
        let tip = options.name(d)
          ? `${options.name(d)}: ${options.yFormat(options.value(d))}`
          : options.yFormat(options.value(d))
        return (
          <Tooltip left={evt.pageX} top={evt.pageY}>

{tip}

          </Tooltip>
        )
      }

      if (this.layer) {
        this.layer._render = render
      } else {
        this.layer = new Layer(document.body, render)
      }

      this.layer.render()
    })
      .on('mouseout', d => {
        if (this.layer) {
          this.layer.destroy()
          this.layer = null
        }
      })

    slice.exit().remove()
  }
})

export default PieChart
<commit_msg>add IE compatible for pie charts<commit_after>import _ from 'lodash'
import d3 from 'd3'
import React from 'react'
import Layer from 'react-layer'

import browser from 'util/browser'
import color from 'util/color'
import palettes from 'util/palettes'
import Tooltip from 'component/Tooltip.jsx'

function _domain (data, options) {
  return [0, _(data).map(options.value).sum()]
}

var DEFAULTS = {
  domain: _domain,
  innerRadius: 0,
  outerRadius: 1,
  margin: {
    top: 0,
    right: 0,
    bottom: 0,
    left: 0
  },
  value: _.property('value'),
  color: palettes.blue,
  name: _.property('indicator.short_name'),
  yFormat: function (d) {
    return d3.format((Math.abs(d) < 1) ? '%' : 'n')(d)
  }
}

function PieChart () {
}

_.extend(PieChart.prototype, {
  defaults: DEFAULTS,

  initialize: function (el, data, options) {
    var opts = this._options = _.defaults({}, options, DEFAULTS)

    this._height = this._width = _.get(opts, 'size', el.clientWidth)

    var svg = this._svg = d3.select(el).append('svg')
      .attr('class', 'pie')
      .attr({
        'viewBox': '0 0 ' + this._width + ' ' + this._height
      })

    if (browser.isIE()) {
      svg.attr({
        'width': this._width,
        'height': this._height
      })
    }

    var g = svg.append('g').attr('class', 'margin')

    g
      .append('g').attr('class', 'data')
      .append('path').attr('class', 'bg')

    g.append('g').attr('class', 'annotation')

    this.update(data)
  },

  update: function (values, options) {
    options = _.assign(this._options, options)
    var margin = options.margin

    values = _(values)
      .filter(d => {
        var v = options.value(d)
        return _.isFinite(v) && v > 0
      })
      .sortBy(options.value)
      .reverse()
      .value()

    let data = []
    if (values.length === 1) {
      // assume single indicator respresenting perentage
      data.push({ value: Math.round(values[0].value * 100) / 100 })
      data.push({ value: 1 - data[0].value })
    } else {
      data = values
    }

    var w = this._width - margin.left - margin.right
    var h = this._height - margin.top - margin.bottom
    var s = Math.min(w, h)

    var svg = this._svg

    svg.select('.margin')
      .attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')')

    var xPosition = options.notInCenter ? w / 4 : w / 2
    var yPosition = options.notInCenter ? h / 3 : h / 2

    let g = svg.select('.data')
      .attr('transform', 'translate(' + xPosition + ', ' + yPosition + ')')

    if (options.percentage) {
      var annotation = svg.select('.annotation').selectAll('.percentage').data([options.percentage])
      annotation.enter().append('text')
      annotation.attr('class', 'percentage')
        .attr({'x': xPosition, 'y': yPosition, 'dy': 5})
        .style({
          'text-anchor': 'middle',
          'opacity': d => { return d === '0%' ? 0 : 1 }
        })
        .text(d => { return d })

      annotation.exit().remove()
    }

    var arc = d3.svg.arc()
      .innerRadius(s / 2 * options.innerRadius)
      .outerRadius(s / 2 * options.outerRadius)

    svg.select('.bg')
      .datum({
        startAngle: 0,
        endAngle: 2 * Math.PI
      })
      .attr('d', arc)

    var scale = d3.scale.linear()
      .domain(options.domain(data, options))
      .range([0, 2 * Math.PI])

    var pie = d3.layout.stack()
      .values(function (d) {
        return [d]
      })
      .x(options.name)
      .y(options.value)
      .out(function (d, y0, y) {
        d.startAngle = scale(y0)
        d.endAngle = scale(y0 + y)
      })

    let fill = color.map(data.map(options.name), options.color)

    var slice = g.selectAll('.slice').data(pie(_.cloneDeep(data)))

    slice.enter()
      .append('path')
      .attr('class', 'slice')

    slice.attr({
      'd': arc,
      'fill': _.flow(options.name, fill),
      'stroke': '#fff'
    }).on('mousemove', d => {
      var evt = d3.event
      var render = function () {
        let tip = options.name(d)
          ? `${options.name(d)}: ${options.yFormat(options.value(d))}`
          : options.yFormat(options.value(d))
        return (
          <Tooltip left={evt.pageX} top={evt.pageY}>

{tip}

          </Tooltip>
        )
      }

      if (this.layer) {
        this.layer._render = render
      } else {
        this.layer = new Layer(document.body, render)
      }

      this.layer.render()
    })
      .on('mouseout', d => {
        if (this.layer) {
          this.layer.destroy()
          this.layer = null
        }
      })

    slice.exit().remove()
  }
})

export default PieChart
<|endoftext|>


<commit_before>import mkdirp from 'mkdirp';
import handlebars from 'handlebars';
import fs from 'fs';
import urlapi from 'url';

export default class ReactCrudGenerator {
  templates = {};

  constructor(hydraPrefix) {
    const templatePath = `${__dirname}/../templates/react/`;

    this.hydraPrefix = hydraPrefix;

    // actions
    this.registerTemplate(templatePath, 'actions/foo/create.js');
    this.registerTemplate(templatePath, 'actions/foo/delete.js');
    this.registerTemplate(templatePath, 'actions/foo/list.js');
    this.registerTemplate(templatePath, 'actions/foo/update.js');
    this.registerTemplate(templatePath, 'actions/foo/show.js');

    // api
    this.registerTemplate(templatePath, 'api/fooFetch.js');

    // components
    this.registerTemplate(templatePath, 'components/foo/Create.js');
    this.registerTemplate(templatePath, 'components/foo/Form.js');
    this.registerTemplate(templatePath, 'components/foo/index.js');
    this.registerTemplate(templatePath, 'components/foo/List.js');
    this.registerTemplate(templatePath, 'components/foo/Update.js');
    this.registerTemplate(templatePath, 'components/foo/Show.js');

    // reducers
    this.registerTemplate(templatePath, 'reducers/foo/create.js');
    this.registerTemplate(templatePath, 'reducers//foo/delete.js');
    this.registerTemplate(templatePath, 'reducers/foo/index.js');
    this.registerTemplate(templatePath, 'reducers/foo/list.js');
    this.registerTemplate(templatePath, 'reducers/foo/update.js');
    this.registerTemplate(templatePath, 'reducers/foo/show.js');

    // routes
    this.registerTemplate(templatePath, 'routes/foo.js');

    // entrypoint
    this.registerTemplate(templatePath, 'api/_entrypoint.js');

    // utils
    this.registerTemplate(templatePath, 'utils/helpers.js');
  }

  registerTemplate(templatePath, path) {
    this.templates[path] = handlebars.compile(fs.readFileSync(templatePath+path).toString());
  }

  generate(api, resource, dir) {
    const lc = resource.title.toLowerCase();
    const titleUcFirst = resource.title.charAt(0).toUpperCase() + resource.title.slice(1);

    const context = {
      title: resource.title,
      name: resource.name,
      lc,
      uc: resource.title.toUpperCase(),
      fields: resource.readableFields,
      formFields: this.buildFields(resource.writableFields),
      hydraPrefix: this.hydraPrefix,
      titleUcFirst
    };

    // Create directories
    // These directories may already exist
    mkdirp.sync(`${dir}/api`);
    mkdirp.sync(`${dir}/routes`);
    mkdirp.sync(`${dir}/utils`);

    this.createDir(`${dir}/actions/${lc}`);
    this.createDir(`${dir}/components/${lc}`);
    this.createDir(`${dir}/reducers/${lc}`);

    // actions
    this.createFile('actions/foo/create.js', `${dir}/actions/${lc}/create.js`, context);
    this.createFile('actions/foo/delete.js', `${dir}/actions/${lc}/delete.js`, context);
    this.createFile('actions/foo/list.js', `${dir}/actions/${lc}/list.js`, context);
    this.createFile('actions/foo/update.js', `${dir}/actions/${lc}/update.js`, context);
    this.createFile('actions/foo/show.js', `${dir}/actions/${lc}/show.js`, context);

    // api
    this.createFile('api/fooFetch.js', `${dir}/api/${lc}Fetch.js`, context);

    // components
    this.createFile('components/foo/Create.js', `${dir}/components/${lc}/Create.js`, context);
    this.createFile('components/foo/Form.js', `${dir}/components/${lc}/Form.js`, context);
    this.createFile('components/foo/index.js', `${dir}/components/${lc}/index.js`, context);
    this.createFile('components/foo/List.js', `${dir}/components/${lc}/List.js`, context);
    this.createFile('components/foo/Update.js', `${dir}/components/${lc}/Update.js`, context);
    this.createFile('components/foo/Show.js', `${dir}/components/${lc}/Show.js`, context);

    // reducers
    this.createFile('reducers/foo/create.js', `${dir}/reducers/${lc}/create.js`, context);
    this.createFile('reducers//foo/delete.js', `${dir}/reducers/${lc}/delete.js`, context);
    this.createFile('reducers/foo/index.js', `${dir}/reducers/${lc}/index.js`, context);
    this.createFile('reducers/foo/list.js', `${dir}/reducers/${lc}/list.js`, context);
    this.createFile('reducers/foo/update.js', `${dir}/reducers/${lc}/update.js`, context);
    this.createFile('reducers/foo/show.js', `${dir}/reducers/${lc}/show.js`, context);

    // routes
    this.createFile('routes/foo.js', `${dir}/routes/${lc}.js`, context)
  }

  entrypoint(apiEntry, dir) {
    const url = urlapi.parse(apiEntry);
    const {protocol, host, port, pathname} = url;
    const hostUrl = `${protocol}//${host}${port ? `:${port}` : ''}`;

    const context = {
      host: hostUrl,
      path: pathname
    }

    this.createFile('api/_entrypoint.js', `${dir}/api/_entrypoint.js`, context);
  }

  utils(dir) {
    this.createFile('utils/helpers.js', `${dir}/utils/helpers.js`, null);
  }

  getInputTypeFromField(field) {
    switch (field.id) {
      case 'http://schema.org/email':
        return {type: 'email'};

      case 'http://schema.org/url':
        return {type: 'url'};
    }

    switch (field.range) {
      case 'http://www.w3.org/2001/XMLSchema#integer':
        return {type: 'number'};

      case 'http://www.w3.org/2001/XMLSchema#decimal':
        return {type: 'number', step: '0.1'};

      case 'http://www.w3.org/2001/XMLSchema#boolean':
        return {type: 'checkbox'};

      case 'http://www.w3.org/2001/XMLSchema#date':
        return {type: 'date'};

      case 'http://www.w3.org/2001/XMLSchema#time':
        return {type: 'time'};

      default:
        return {type: 'text'};
    }
  }

  buildFields(apiFields) {
    let fields = [];
    for (let apiField of apiFields) {
      let field = this.getInputTypeFromField(apiField);
      field.required = apiField.required;
      field.name = apiField.name;
      field.description = apiField.description.replace(/"/g, "'"); // fix for Form placeholder description

      fields.push(field)
    }

    return fields;
  }

  createDir(dir) {
    if (fs.existsSync(dir)) throw new Error(`The directory "${dir}" already exists`);
    mkdirp.sync(dir);
  }

  createFile(template, dest, context) {
    fs.writeFileSync(dest, this.templates[template](context));
  }
}
<commit_msg>API_PATH<commit_after>import mkdirp from 'mkdirp';
import handlebars from 'handlebars';
import fs from 'fs';
import urlapi from 'url';

export default class ReactCrudGenerator {
  templates = {};

  constructor(hydraPrefix) {
    const templatePath = `${__dirname}/../templates/react/`;

    this.hydraPrefix = hydraPrefix;

    // actions
    this.registerTemplate(templatePath, 'actions/foo/create.js');
    this.registerTemplate(templatePath, 'actions/foo/delete.js');
    this.registerTemplate(templatePath, 'actions/foo/list.js');
    this.registerTemplate(templatePath, 'actions/foo/update.js');
    this.registerTemplate(templatePath, 'actions/foo/show.js');

    // api
    this.registerTemplate(templatePath, 'api/fooFetch.js');

    // components
    this.registerTemplate(templatePath, 'components/foo/Create.js');
    this.registerTemplate(templatePath, 'components/foo/Form.js');
    this.registerTemplate(templatePath, 'components/foo/index.js');
    this.registerTemplate(templatePath, 'components/foo/List.js');
    this.registerTemplate(templatePath, 'components/foo/Update.js');
    this.registerTemplate(templatePath, 'components/foo/Show.js');

    // reducers
    this.registerTemplate(templatePath, 'reducers/foo/create.js');
    this.registerTemplate(templatePath, 'reducers//foo/delete.js');
    this.registerTemplate(templatePath, 'reducers/foo/index.js');
    this.registerTemplate(templatePath, 'reducers/foo/list.js');
    this.registerTemplate(templatePath, 'reducers/foo/update.js');
    this.registerTemplate(templatePath, 'reducers/foo/show.js');

    // routes
    this.registerTemplate(templatePath, 'routes/foo.js');

    // entrypoint
    this.registerTemplate(templatePath, 'api/_entrypoint.js');

    // utils
    this.registerTemplate(templatePath, 'utils/helpers.js');
  }

  registerTemplate(templatePath, path) {
    this.templates[path] = handlebars.compile(fs.readFileSync(templatePath+path).toString());
  }

  generate(api, resource, dir) {
    const lc = resource.title.toLowerCase();
    const titleUcFirst = resource.title.charAt(0).toUpperCase() + resource.title.slice(1);

    const context = {
      title: resource.title,
      name: resource.name,
      lc,
      uc: resource.title.toUpperCase(),
      fields: resource.readableFields,
      formFields: this.buildFields(resource.writableFields),
      hydraPrefix: this.hydraPrefix,
      titleUcFirst
    };

    // Create directories
    // These directories may already exist
    mkdirp.sync(`${dir}/api`);
    mkdirp.sync(`${dir}/routes`);
    mkdirp.sync(`${dir}/utils`);

    this.createDir(`${dir}/actions/${lc}`);
    this.createDir(`${dir}/components/${lc}`);
    this.createDir(`${dir}/reducers/${lc}`);

    // actions
    this.createFile('actions/foo/create.js', `${dir}/actions/${lc}/create.js`, context);
    this.createFile('actions/foo/delete.js', `${dir}/actions/${lc}/delete.js`, context);
    this.createFile('actions/foo/list.js', `${dir}/actions/${lc}/list.js`, context);
    this.createFile('actions/foo/update.js', `${dir}/actions/${lc}/update.js`, context);
    this.createFile('actions/foo/show.js', `${dir}/actions/${lc}/show.js`, context);

    // api
    this.createFile('api/fooFetch.js', `${dir}/api/${lc}Fetch.js`, context);

    // components
    this.createFile('components/foo/Create.js', `${dir}/components/${lc}/Create.js`, context);
    this.createFile('components/foo/Form.js', `${dir}/components/${lc}/Form.js`, context);
    this.createFile('components/foo/index.js', `${dir}/components/${lc}/index.js`, context);
    this.createFile('components/foo/List.js', `${dir}/components/${lc}/List.js`, context);
    this.createFile('components/foo/Update.js', `${dir}/components/${lc}/Update.js`, context);
    this.createFile('components/foo/Show.js', `${dir}/components/${lc}/Show.js`, context);

    // reducers
    this.createFile('reducers/foo/create.js', `${dir}/reducers/${lc}/create.js`, context);
    this.createFile('reducers//foo/delete.js', `${dir}/reducers/${lc}/delete.js`, context);
    this.createFile('reducers/foo/index.js', `${dir}/reducers/${lc}/index.js`, context);
    this.createFile('reducers/foo/list.js', `${dir}/reducers/${lc}/list.js`, context);
    this.createFile('reducers/foo/update.js', `${dir}/reducers/${lc}/update.js`, context);
    this.createFile('reducers/foo/show.js', `${dir}/reducers/${lc}/show.js`, context);

    // routes
    this.createFile('routes/foo.js', `${dir}/routes/${lc}.js`, context)
  }

  entrypoint(apiEntry, dir) {
    const url = urlapi.parse(apiEntry);
    const {protocol, host, port, pathname} = url;
    const hostUrl = `${protocol}//${host}${port ? `:${port}` : ''}`;

    const context = {
      host: hostUrl,
      path: pathname + '/'
    }

    this.createFile('api/_entrypoint.js', `${dir}/api/_entrypoint.js`, context);
  }

  utils(dir) {
    this.createFile('utils/helpers.js', `${dir}/utils/helpers.js`, null);
  }

  getInputTypeFromField(field) {
    switch (field.id) {
      case 'http://schema.org/email':
        return {type: 'email'};

      case 'http://schema.org/url':
        return {type: 'url'};
    }

    switch (field.range) {
      case 'http://www.w3.org/2001/XMLSchema#integer':
        return {type: 'number'};

      case 'http://www.w3.org/2001/XMLSchema#decimal':
        return {type: 'number', step: '0.1'};

      case 'http://www.w3.org/2001/XMLSchema#boolean':
        return {type: 'checkbox'};

      case 'http://www.w3.org/2001/XMLSchema#date':
        return {type: 'date'};

      case 'http://www.w3.org/2001/XMLSchema#time':
        return {type: 'time'};

      default:
        return {type: 'text'};
    }
  }

  buildFields(apiFields) {
    let fields = [];
    for (let apiField of apiFields) {
      let field = this.getInputTypeFromField(apiField);
      field.required = apiField.required;
      field.name = apiField.name;
      field.description = apiField.description.replace(/"/g, "'"); // fix for Form placeholder description

      fields.push(field)
    }

    return fields;
  }

  createDir(dir) {
    if (fs.existsSync(dir)) throw new Error(`The directory "${dir}" already exists`);
    mkdirp.sync(dir);
  }

  createFile(template, dest, context) {
    fs.writeFileSync(dest, this.templates[template](context));
  }
}
<|endoftext|>


<commit_before>import chalk from "chalk";
import esprima from "esprima";
import yargs from "yargs";
import * as Styx from "../../styx/dist/transpiled/styx";

import fs from "fs";

import { validateCommandLineArgs } from "./argValidator";
import help from "./help";

// ============================================================================

const commandLineArgs = yargs
    .alias("i", "input")
    .alias("o", "output")
    .alias("f", "format")
    .argv;

runStyx(commandLineArgs);

function runStyx(args) {
    if (args.help) {
        help.show();
        return;
    }

    const argumentErrors = validateCommandLineArgs(args);

    if (argumentErrors.length) {
        const errorMessage = argumentErrors.join("\n");
        exitWithError(errorMessage);
    }

    processInputFile(args);
}

function processInputFile(args) {
    fs.readFile(args.input, "utf-8", function(err, fileContents) {
        if (err) {
            exitWithError(`Couldn't read input file "${err.path}".`);
        }

        const ast = esprima.parse(fileContents);
        const flowProgram = Styx.parse(ast);
        const exportedProgram = Styx.exportProgram(flowProgram, args.format);

        if (args.output) {
            writeExportToFile(exportedProgram, args);
        } else {
            console.log(exportedProgram);
        }
    });
}

function writeExportToFile(exportedProgram, args) {
    fs.writeFile(args.output, exportedProgram, function(err) {
        if (err) {
            exitWithError(err);
        }

        console.log(chalk.bold.green("Export successful."));
    });
}

function displayError(errorMessage) {
    console.log(chalk.red.bold(errorMessage));
}

function exitWithError(errorMessage) {
    displayError(errorMessage);
    process.exit(1);
}
<commit_msg>Clarifies array length check<commit_after>import chalk from "chalk";
import esprima from "esprima";
import yargs from "yargs";
import * as Styx from "../../styx/dist/transpiled/styx";

import fs from "fs";

import { validateCommandLineArgs } from "./argValidator";
import help from "./help";

// ============================================================================

const commandLineArgs = yargs
    .alias("i", "input")
    .alias("o", "output")
    .alias("f", "format")
    .argv;

runStyx(commandLineArgs);

function runStyx(args) {
    if (args.help) {
        help.show();
        return;
    }

    const argumentErrors = validateCommandLineArgs(args);

    if (argumentErrors.length > 0) {
        const errorMessage = argumentErrors.join("\n");
        exitWithError(errorMessage);
    }

    processInputFile(args);
}

function processInputFile(args) {
    fs.readFile(args.input, "utf-8", function(err, fileContents) {
        if (err) {
            exitWithError(`Couldn't read input file "${err.path}".`);
        }

        const ast = esprima.parse(fileContents);
        const flowProgram = Styx.parse(ast);
        const exportedProgram = Styx.exportProgram(flowProgram, args.format);

        if (args.output) {
            writeExportToFile(exportedProgram, args);
        } else {
            console.log(exportedProgram);
        }
    });
}

function writeExportToFile(exportedProgram, args) {
    fs.writeFile(args.output, exportedProgram, function(err) {
        if (err) {
            exitWithError(err);
        }

        console.log(chalk.bold.green("Export successful."));
    });
}

function displayError(errorMessage) {
    console.log(chalk.red.bold(errorMessage));
}

function exitWithError(errorMessage) {
    displayError(errorMessage);
    process.exit(1);
}
<|endoftext|>


<commit_before>import React, {Component} from "react"
import Codemirror from 'react-codemirror'
import {html as html_beautify} from 'js-beautify'
import Modal from 'react-modal'
require('codemirror/mode/htmlmixed/htmlmixed');

export default class CodeMirror extends Component {
    constructor(props) {
        super(props);

        this.onClickBound = this.onClick.bind(this);

        this.beautifyOptions = {
            "wrap_line_length": 140
        };
        if (this.props.node) {
            this.state = {
                sourceEditorActive: false
            };
        } else {
            this.state = {}
        }
        this.code = this.props.data && this.props.data.html || this.props.html;

        if(this.props.data) {
            this.initDataKeys = Object.keys(this.props.data);
        }
    }

    setEditorActive(active) {
        if(active != this.state.sourceEditorActive) {
            this.setState({sourceEditorActive: active});
            this.props.onEditorActive && this.props.onEditorActive(this.props.id, active);
        }
    }

    /**
     * That is a common public method that should activate component editor if it presents
     */
    activateEditor() {
        if(this.props.editorActive && !this.state.sourceEditorActive) {
            this.setEditorActive(true);
        }
    }

    deactivateEditor() {
        if(this.props.editorActive && this.state.sourceEditorActive) {
            this.setEditorActive(false);
        }
    }

    componentWillReceiveProps(newProps) {
        if(newProps.manualActivation) {
            this.props.onManualActivation(this.props.id);
            this.activateEditor();
        }
        if(newProps.manualDeactivation) {
            this.props.onManualDeactivation(this.props.id);
            this.deactivateEditor();
        }
    }

    componentWillUnmount(){
        console.log(`Code mirror ${this.props.id} unmounted`);
    }

    updateCode(newCode) {
        this.code = newCode
    }

    shouldComponentUpdate(nextProps, nextState){
        let data = this.props.data;
        if (data) {
            let needRender = data.updateNode != undefined && data.updateNode != null ? data.updateNode : true;
            if (!needRender && nextProps.data != this.props.data) {
                let isChanged = false;
                this.initDataKeys.forEach(key => isChanged = isChanged && (nextProps.data[key] != this.props.data[key]));
                this.props.setPieceMessage && this.props.setPieceMessage(this.props.id, 'Page refresh required', 'warning');
            }
        }
        return true;
    }

    componentDidUpdate() {
        this.nodeWasUpdated && this.props.onNodeResized && this.props.onNodeResized(this.props.id);
    }

    onSave() {
        this.props.updatePiece && this.props.updatePiece(this.props.id, {data: {html: this.code, updateNode: this.props.data.updateNode}});
        this.props.savePiece && this.props.savePiece(this.props.id);
        this.setEditorActive(false);
    }

    onClose() {
        this.props.node ? this.setEditorActive(false) : (this.props.onClose && this.props.onClose())
    }

    createEditor(){
        // this.props.node
        if(this.props.node) {
            this.props.node.addEventListener('click', this.onClickBound);
        }
    }

    destroyEditor(){
        if(this.props.node) {
            this.props.node.removeEventListener('click', this.onClickBound);
        }
    }

    renderNonReactAttributes(){
        if (this.props.editorActive && !this.state.sourceEditorActive) {
            this.createEditor();
            if(this.props.node) {
                this.props.node.classList.add(...this.props.className.split(' '));
            }
        }
        else {
            this.destroyEditor();
            if(this.props.node) {
                this.props.node.classList.remove(...this.props.className.split(' '));
            }
        }

        this.nodeWasUpdated = false;
        //render new data
        if(this.props.node) {
            let content = this.props.node.innerHTML;
            let data = this.props.data;
            let needRender = data.updateNode != undefined && data.updateNode != null ? data.updateNode : true;
            if (content != data.html && needRender == true) {
                this.props.node.innerHTML = data.html;
                this.nodeWasUpdated = true;
            }
        }

    }

    onClick(e){
        e.preventDefault();
        e.stopPropagation();
        this.setEditorActive(true);
    }

    handleCloseModal(event){
        if(event.type == 'keydown' && event.keyCode === 27) {
            this.modalNode.parentNode.dispatchEvent(new KeyboardEvent('keyDown', {key: 'Escape'}));
        }
    }

    render() {
        let codemirror = null;

        if(this.state.sourceEditorActive || !this.props.node){
            //if there is no this.props.node, it means this component is invoked manually with custom html directly in props and should be just rendered
            //if this.state.sourceEditorActive and this.props.node presents, it means that is a regular piece with control over node and sourceEditorActive means modal is open
            let options = {
                lineNumbers: true,
                mode: 'htmlmixed'
            };
            const html = this.props.node ? this.props.data.html : this.props.html;
            codemirror =  <Modal contentLabel="Edit source" isOpen={true} overlayClassName="r_modal-overlay r_visible"
                                 className="r_modal-content" ref={(modal) => this.modalNode = (modal && modal.node)}
                                 onRequestClose={this.handleCloseModal().bind(this)}>
                <Codemirror
                    value={html_beautify(html)}
                    onChange={this.updateCode.bind(this)} options={options}/>

Cancel

this.props.node ? this.onSave() : (this.props.onSave && this.props.onSave(this.code))}>
                        Save

            </Modal>;
        } else {
            codemirror = React.createElement(this.props.wrapper, {});
        }

        this.renderNonReactAttributes();
        return codemirror;
    }
}

/**
 * Specify component should be rendered inside target node and capture all inside html
 * @type {string}
 */
CodeMirror.__renderType = "BEFORE";
CodeMirror.__name = "Source code";
<commit_msg>added a new field<commit_after>import React, {Component} from "react"
import Codemirror from 'react-codemirror'
import {html as html_beautify} from 'js-beautify'
import Modal from 'react-modal'
require('codemirror/mode/htmlmixed/htmlmixed');

export default class CodeMirror extends Component {
    constructor(props) {
        super(props);

        this.onClickBound = this.onClick.bind(this);

        this.beautifyOptions = {
            "wrap_line_length": 140
        };
        if (this.props.node) {
            this.state = {
                sourceEditorActive: false
            };
        } else {
            this.state = {}
        }
        this.code = this.props.data && this.props.data.html || this.props.html;

        if(this.props.data) {
            this.initDataKeys = Object.keys(this.props.data);
        }
    }

    setEditorActive(active) {
        if(active != this.state.sourceEditorActive) {
            this.setState({sourceEditorActive: active});
            this.props.onEditorActive && this.props.onEditorActive(this.props.id, active);
        }
    }

    /**
     * That is a common public method that should activate component editor if it presents
     */
    activateEditor() {
        if(this.props.editorActive && !this.state.sourceEditorActive) {
            this.setEditorActive(true);
        }
    }

    deactivateEditor() {
        if(this.props.editorActive && this.state.sourceEditorActive) {
            this.setEditorActive(false);
        }
    }

    componentWillReceiveProps(newProps) {
        if(newProps.manualActivation) {
            this.props.onManualActivation(this.props.id);
            this.activateEditor();
        }
        if(newProps.manualDeactivation) {
            this.props.onManualDeactivation(this.props.id);
            this.deactivateEditor();
        }
    }

    componentWillUnmount(){
        console.log(`Code mirror ${this.props.id} unmounted`);
    }

    updateCode(newCode) {
        this.code = newCode
    }

    shouldComponentUpdate(nextProps, nextState){
        let data = this.props.data;
        if (data) {
            let needRender = data.updateNode != undefined && data.updateNode != null ? data.updateNode : true;
            if (!needRender && nextProps.data != this.props.data) {
                let isChanged = false;
                this.initDataKeys.forEach(key => isChanged = isChanged && (nextProps.data[key] != this.props.data[key]));
                this.props.setPieceMessage && this.props.setPieceMessage(this.props.id, 'Page refresh required', 'warning');
            }
        }
        return true;
    }

    componentDidUpdate() {
        this.nodeWasUpdated && this.props.onNodeResized && this.props.onNodeResized(this.props.id);
    }

    onSave() {
        this.props.updatePiece && this.props.updatePiece(this.props.id, {data: {html: this.code, updateNode: this.props.data.updateNode}});
        this.props.savePiece && this.props.savePiece(this.props.id);
        this.setEditorActive(false);
    }

    onClose() {
        this.props.node ? this.setEditorActive(false) : (this.props.onClose && this.props.onClose())
    }

    createEditor(){
        // this.props.node
        if(this.props.node) {
            this.props.node.addEventListener('click', this.onClickBound);
        }
    }

    destroyEditor(){
        if(this.props.node) {
            this.props.node.removeEventListener('click', this.onClickBound);
        }
    }

    renderNonReactAttributes(){
        if (this.props.editorActive && !this.state.sourceEditorActive) {
            this.createEditor();
            if(this.props.node) {
                this.props.node.classList.add(...this.props.className.split(' '));
            }
        }
        else {
            this.destroyEditor();
            if(this.props.node) {
                this.props.node.classList.remove(...this.props.className.split(' '));
            }
        }

        this.nodeWasUpdated = false;
        //render new data
        if(this.props.node) {
            let content = this.props.node.innerHTML;
            let data = this.props.data;
            let needRender = data.updateNode != undefined && data.updateNode != null ? data.updateNode : true;
            if (content != data.html && needRender == true) {
                this.props.node.innerHTML = data.html;
                this.nodeWasUpdated = true;
            }
        }

    }

    onClick(e){
        e.preventDefault();
        e.stopPropagation();
        this.setEditorActive(true);
    }

    handleCloseModal(event){
        if(event.type == 'keydown' && event.keyCode === 27) {
            this.modalNode.parentNode.dispatchEvent(new KeyboardEvent('keyDown', {key: 'Escape'}));
        }
    }

    render() {
        let codemirror = null;

        if(this.state.sourceEditorActive || !this.props.node){
            //if there is no this.props.node, it means this component is invoked manually with custom html directly in props and should be just rendered
            //if this.state.sourceEditorActive and this.props.node presents, it means that is a regular piece with control over node and sourceEditorActive means modal is open
            let options = {
                lineNumbers: true,
                mode: 'htmlmixed'
            };
            const html = this.props.node ? this.props.data.html : this.props.html;
            codemirror =  <Modal contentLabel="Edit source" isOpen={true} overlayClassName="r_modal-overlay r_visible"
                                 className="r_modal-content" ref={(modal) => this.modalNode = (modal && modal.node)}
                                 onRequestClose={this.handleCloseModal().bind(this)}>
                <Codemirror
                    value={html_beautify(html)}
                    onChange={this.updateCode.bind(this)} options={options}/>

Cancel

this.props.node ? this.onSave() : (this.props.onSave && this.props.onSave(this.code))}>
                        Save

            </Modal>;
        } else {
            codemirror = React.createElement(this.props.wrapper, {});
        }

        this.renderNonReactAttributes();
        return codemirror;
    }
}

/**
 * Specify component should be rendered inside target node and capture all inside html
 * @type {string}
 */
CodeMirror.__renderType = "BEFORE";
CodeMirror.__editLabel = "Edit Source Code";
<|endoftext|>


<commit_before>(function(){
    var controls = [
        new OpenLayers.Control.TouchNavigation({
            dragPanOptions: {
                enableKinetic: true
            }
        }),
        new OpenLayers.Control.Attribution(),
        new OpenLayers.Control.Scale(),
        new OpenLayers.Control.Navigation(),
        new OpenLayers.Control.LayerSwitcher(),
        new OpenLayers.Control.MousePosition(),
        new OpenLayers.Control.PanZoomBar()
    ];

    map = new OpenLayers.Map('map', {controls: controls});

    var base_osm = new OpenLayers.Layer.OSM("OpenStreetMap");
    map.addLayer(base_osm);

    map.setCenter(
        new OpenLayers.LonLat(-4.356, 53.286).transform(
            new OpenLayers.Projection("EPSG:4326"),
            map.getProjectionObject()
        ),
        10
    );

})();
<commit_msg>Add project_area overlay layer<commit_after>(function(){
    var controls = [
        new OpenLayers.Control.TouchNavigation({
            dragPanOptions: {
                enableKinetic: true
            }
        }),
        new OpenLayers.Control.Attribution(),
        new OpenLayers.Control.Scale(),
        new OpenLayers.Control.Navigation(),
        new OpenLayers.Control.LayerSwitcher(),
        new OpenLayers.Control.MousePosition(),
        new OpenLayers.Control.PanZoomBar()
    ];

    map = new OpenLayers.Map('map', {controls: controls});

    var base_osm = new OpenLayers.Layer.OSM("OpenStreetMap");
    map.addLayer(base_osm);

    var project_area = wmsLayer(
        "Project Area",
        'http://localhost/cgi-bin/mapserv?map=/home/matt/Software/FishMap/config/mapserver/fishmap.map',
        {
            layers: 'project_area'
        },
        {}
    );
    map.addLayer(project_area);

    map.setCenter(
        new OpenLayers.LonLat(-4.356, 53.286).transform(
            new OpenLayers.Projection("EPSG:4326"),
            map.getProjectionObject()
        ),
        10
    );

    function wmsLayer(name, path, wms_options, layer_options) {
        var urls = path;
        var lyr = new OpenLayers.Layer.WMS(name, urls,
                    OpenLayers.Util.applyDefaults(wms_options,
                        {
                            version: '1.1.1',
                            format: 'image/png',
                            transparent: true
                        }),
                    OpenLayers.Util.applyDefaults(layer_options,
                        {
                            projection: 'EPSG:900913',
                            singleTile: true,
                            buffer: 0,
                            ratio: 1
                        })
                );
        map.addLayer(lyr);
        return lyr;
    }
})();
<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import merge from 'lodash/merge';
import clamp from 'lodash/clamp';
import raf from 'raf';

import computePosition from './computePosition';
import computeDeltas from './computeDeltas';

const T = React.PropTypes;

// HACK
document.body.oncontextmenu = function() { return false; };

class Touchable extends React.Component {
  static propTypes = {
    children: T.oneOfType([T.func, T.element]).isRequired,
    style: T.objectOf(T.oneOfType([T.number, T.object])).isRequired,
    onTouchStart: T.func,
    onTouchEnd: T.func,
    onTouchMove: T.func,
    onSwipe: T.func,
    onHold: T.func,
  };

  state = {
    component: {
      initial: {
        position: computePosition(this.props.style, { dx: 0, dy: 0 }),
      },
      current: {
        position: computePosition(this.props.style, { dx: 0, dy: 0 }),
      },
    },
    touch: {
      initial: {
        position: null,
        time: null
      },
      current: {
        position: null,
        time: null
      },
    }
  };

  _updatingPosition = false;
  _holdDownTimer = null;
  _holdReleaseTimer = null;

  // TODO: configurable
  DEFAULT_HOLD_INTERVAL = 250;
  DEFAULT_HOLD_LENGTH = 1000;

  onTouchStart(e) {
    // TODO: touches, targetTouches, or changedTouches
    const { clientX: x, clientY: y } = e.nativeEvent.touches[0];
    const dimensions = { position: { x, y }, time: new Date() };

    const touch = merge({}, this.state.touch, {
      initial: dimensions,
      current: dimensions
    });
    this.setState({ touch });

    // configuration stuff
    this._holdDownTimer = window.setInterval(() => {
      const touch = merge({}, this.state.touch, { current: { time: new Date() }})
      this.setState({ touch });
    }, this.DEFAULT_HOLD_INTERVAL);

    this._holdReleaseTimer = window.setTimeout(() => {
      this._callPropsHandler('onHold');
    }, this.DEFAULT_HOLD_LENGTH);

    this._callPropsHandler('onTouchStart', e);
  }

  onTouchMove(e) {
    if (!this._updatingPosition) {
      const { clientX: x, clientY: y } = e.nativeEvent.touches[0];
      raf(() => this._updatePosition({x, y}));
    }
    this._updatingPosition = true;
    this._clearHoldTimers();
    this._callPropsHandler('onTouchMove', e);
  }

  _updatePosition(touchPosition) {
    this._updatingPosition = false;

    const deltas = computeDeltas(this.state.touch.current, touchPosition);
    const componentPosition = computePosition(this.state.component.current, deltas);

    const state = merge({}, this.state, {
      touch: {current: { position: touchPosition }},
      component: {current: { position: componentPosition }},
    });

    this.setState({ state });
  }

  onTouchEnd(e) {
    this._clearHoldTimers();
    this._callPropsHandler('onTouchEnd', e);
  }

  _clearHoldTimers() {
    window.clearInterval(this._holdDownTimer);
    window.clearTimeout(this._holdReleaseTimer);
  }

  _callPropsHandler(name, e) {
    // handle user's touch handling
    // TODO: there's not always an e
    this.props[name] && this.props[name](e);
  }

  _calculateHoldPercent(current, initial) {
    if (current.time) {
      const percent = (current.time - initial.time) / this.DEFAULT_HOLD_LENGTH;
      return clamp(percent, 0, 1);
    }
    return 0;
  }

  render() {
    const { children } = this.props;
    const { component, touch } = this.state;

    const holdPercent = this._calculateHoldPercent(touch.current, touch.initial);
    const newProps = { ...component.current.position, holdPercent };

    return React.cloneElement(React.Children.only(children(newProps)), {
      onTouchStart: e => this.onTouchStart(e),
      onTouchMove: e => this.onTouchMove(e),
      onTouchEnd: e => this.onTouchEnd(e),
    });
  }
}

export default Touchable;
<commit_msg>fix a bug<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import merge from 'lodash/merge';
import clamp from 'lodash/clamp';
import raf from 'raf';

import computePosition from './computePosition';
import computeDeltas from './computeDeltas';

const T = React.PropTypes;

// HACK
document.body.oncontextmenu = function() { return false; };

class Touchable extends React.Component {
  static propTypes = {
    children: T.oneOfType([T.func, T.element]).isRequired,
    style: T.objectOf(T.oneOfType([T.number, T.object])).isRequired,
    onTouchStart: T.func,
    onTouchEnd: T.func,
    onTouchMove: T.func,
    onSwipe: T.func,
    onHold: T.func,
  };

  state = {
    component: {
      initial: {
        position: computePosition(this.props.style, { dx: 0, dy: 0 }),
      },
      current: {
        position: computePosition(this.props.style, { dx: 0, dy: 0 }),
      },
    },
    touch: {
      initial: {
        position: null,
        time: null
      },
      current: {
        position: null,
        time: null
      },
    }
  };

  _updatingPosition = false;
  _holdDownTimer = null;
  _holdReleaseTimer = null;

  // TODO: configurable
  DEFAULT_HOLD_INTERVAL = 250;
  DEFAULT_HOLD_LENGTH = 1000;

  onTouchStart(e) {
    // TODO: touches, targetTouches, or changedTouches
    const { clientX: x, clientY: y } = e.nativeEvent.touches[0];
    const dimensions = { position: { x, y }, time: new Date() };

    this.setState(merge({}, this.state, {
      touch: {
        initial: dimensions,
        current: dimensions
      }
    }));

    // configuration stuff
    this._holdDownTimer = window.setInterval(() => {
      this.setState(merge({}, this.state, {
        touch: { current: { time: new Date() }}
      }));
    }, this.DEFAULT_HOLD_INTERVAL);

    this._holdReleaseTimer = window.setTimeout(() => {
      this._callPropsHandler('onHold');
    }, this.DEFAULT_HOLD_LENGTH);

    this._callPropsHandler('onTouchStart', e);
  }

  onTouchMove(e) {
    if (!this._updatingPosition) {
      const { clientX: x, clientY: y } = e.nativeEvent.touches[0];
      raf(() => this._updatePosition({x, y}));
    }
    this._updatingPosition = true;
    this._clearHoldTimers();
    this._callPropsHandler('onTouchMove', e);
  }

  _updatePosition(touchPosition) {
    this._updatingPosition = false;

    const { touch, component } = this.state;
    const deltas = computeDeltas(touch.current.position, touchPosition);
    const componentPosition = computePosition(component.current.position, deltas);

    this.setState(merge({}, this.state, {
      touch: {current: { position: touchPosition }},
      component: {current: { position: componentPosition }},
    }));
  }

  onTouchEnd(e) {
    this._clearHoldTimers();
    this._callPropsHandler('onTouchEnd', e);
  }

  _clearHoldTimers() {
    window.clearInterval(this._holdDownTimer);
    window.clearTimeout(this._holdReleaseTimer);
  }

  _callPropsHandler(name, e) {
    // handle user's touch handling
    // TODO: there's not always an e
    this.props[name] && this.props[name](e);
  }

  _calculateHoldPercent(current, initial) {
    if (current.time) {
      const percent = (current.time - initial.time) / this.DEFAULT_HOLD_LENGTH;
      return clamp(percent, 0, 1);
    }
    return 0;
  }

  render() {
    const { children } = this.props;
    const { component, touch } = this.state;

    const holdPercent = this._calculateHoldPercent(touch.current, touch.initial);
    const newProps = { ...component.current.position, holdPercent };

    return React.cloneElement(React.Children.only(children(newProps)), {
      onTouchStart: e => this.onTouchStart(e),
      onTouchMove: e => this.onTouchMove(e),
      onTouchEnd: e => this.onTouchEnd(e),
    });
  }
}

export default Touchable;
<|endoftext|>


<commit_before>/**
 * Dependencies
 */
const {JSONSchema} = require('@trust/json-document')

/**
 * RelyingParty Schema
 *
 * This schema initializes and verifies Relying Party client configuration.
 * RelyingParty objects can be persisted and rehydrated. By encapsulating this data in
 * it's own class, it's possible to have multiple RP configurations running
 * simultaneously.
 */
const RelyingPartySchema = new JSONSchema({
  type: 'object',
  properties: {

    /**
     * provider
     *
     * Information about the provider, including issuer URL, human readable name,
     * and any configuration or provider metadata retrieved from the OP.
     */
    provider: {
      type: 'object',
      properties: {
        name: { type: 'string' },
        url: { type: 'string', format: 'uri' },
        // NOTE:
        // OpenID Configuration (discovery response) and JSON Web Keys Set for an
        // issuer can be cached here. However the cache should not be persisted or
        // relied upon.
        //
        configuration: {}, // .well-known/openid-configuration
        jwks: {}           // /jwks
      },
      required: ['url']
    },

    /**
     * defaults
     *
     * Default request parameters for authentication and dynamic registration requests.
     * These values can be extended or overridden via arguments to the respective
     * request methods.
     *
     * These are part of the relying party client configuration and can be serialized
     * and persisted.
     */
    defaults: {
      type: 'object',
      properties: {

        /**
         * Default authentication request parameters
         */
        authenticate: {
          type: 'object',
          properties: {
            redirect_uri: {
              type: 'string',
              format: 'uri'
            },
            response_type: {
              type: 'string',
              default: 'id_token token', // browser detection
              enum: [
                'code',
                'token',
                'id_token token',
                'id_token token code'
              ]
            },
            display: {
              type: 'string',
              default: 'page',
              enum: [
                'page',
                'popup'
              ]
            },
            scope: {
              type: ['string', 'array'],
              default: ['openid']
            }
          }
        },

        /**
         * Default client registration parameters
         */
        register: {}
      }
    },

    /**
     * registration
     *
     * This is the client registration response from dynamic registration. It should
     * always reflect the client configuration on the openid provider. A client access
     * token is stored here
     */
    registration: {},// ClientMetadataSchema

    /**
     * store
     */
    store: {
      type: 'object',
      default: {}
    }
  }
})

/**
 * Export
 */
module.exports = RelyingPartySchema
<commit_msg>refactor(RelyingPartySchema): Add popToken semantics flag to RP defaults<commit_after>/**
 * Dependencies
 */
const {JSONSchema} = require('@trust/json-document')

/**
 * RelyingParty Schema
 *
 * This schema initializes and verifies Relying Party client configuration.
 * RelyingParty objects can be persisted and rehydrated. By encapsulating this data in
 * it's own class, it's possible to have multiple RP configurations running
 * simultaneously.
 */
const RelyingPartySchema = new JSONSchema({
  type: 'object',
  properties: {

    /**
     * provider
     *
     * Information about the provider, including issuer URL, human readable name,
     * and any configuration or provider metadata retrieved from the OP.
     */
    provider: {
      type: 'object',
      properties: {
        name: { type: 'string' },
        url: { type: 'string', format: 'uri' },
        // NOTE:
        // OpenID Configuration (discovery response) and JSON Web Keys Set for an
        // issuer can be cached here. However the cache should not be persisted or
        // relied upon.
        //
        configuration: {}, // .well-known/openid-configuration
        jwks: {}           // /jwks
      },
      required: ['url']
    },

    /**
     * defaults
     *
     * Default request parameters for authentication and dynamic registration requests.
     * These values can be extended or overridden via arguments to the respective
     * request methods.
     *
     * These are part of the relying party client configuration and can be serialized
     * and persisted.
     */
    defaults: {
      type: 'object',
      properties: {

        /**
         * Use Proof of Possession token semantics for the ID Token
         */
        popToken: {
          type: 'boolean',
          default: false
        },

        /**
         * Default authentication request parameters
         */
        authenticate: {
          type: 'object',
          properties: {
            redirect_uri: {
              type: 'string',
              format: 'uri'
            },
            response_type: {
              type: 'string',
              default: 'id_token token', // browser detection
              enum: [
                'code',
                'token',
                'id_token token',
                'id_token token code'
              ]
            },
            display: {
              type: 'string',
              default: 'page',
              enum: [
                'page',
                'popup'
              ]
            },
            scope: {
              type: ['string', 'array'],
              default: ['openid']
            }
          }
        },

        /**
         * Default client registration parameters
         */
        register: {}
      }
    },

    /**
     * registration
     *
     * This is the client registration response from dynamic registration. It should
     * always reflect the client configuration on the openid provider. A client access
     * token is stored here
     */
    registration: {},// ClientMetadataSchema

    /**
     * store
     */
    store: {
      type: 'object',
      default: {}
    }
  }
})

/**
 * Export
 */
module.exports = RelyingPartySchema
<|endoftext|>


<commit_before>var _ = require('underscore'),
	async = require('async'),
	cast = require('sc-cast'),
	crypto = require('crypto'),
	fs = require('fs'),
	os = require('os'),
	gm = require('gm'),
	https = require('https'),
	http = require('http');

module.exports = function (_config) {
	var config = _.extend({

		cacheFolder: os.tmpdir(),
		ttl: 1000 * 60 * 60 * 24 * 7, // 1 week
		allowProxy: true,
		imageDir: process.cwd(),

	}, _config);

	return function (_req, _res, _next) {
		var dimensions = _req.query.resize || '0x0',
			crop = _req.query.crop || '0x0',
			quality = _req.query.quality;

		var gmOptions = {};
		if(config.imageMagick) {
			gmOptions.imageMagick = config.imageMagick;
		}
		if(config.graphicsMagick) {
			gmOptions.graphicsMagick = config.graphicsMagick;
		}

		var image = {
			query: JSON.stringify(_req.query),
			location: _req.query.image,
			resize: {
				width: cast(_.first(dimensions.match(/^[^x]+/)), 'number') || null,
				height: cast(_.first(dimensions.match(/[^x]+$/)), 'number') || null
			},
			crop: {
				width: cast(_.first(crop.match(/^[^x]+/)), 'number') || null,
				height: cast(_.first(crop.match(/[^x]+$/)), 'number') || null
			},
			size: {
				width: 0,
				height: 0
			},
			quality: cast(quality, 'number'),
			upscale: /true/i.test(_req.query.upscale)
		};

		if(config.allowProxy && !/^https?\:/.test(image.location)) {
			image.location = image.location.trim().replace(/^\//, '');
			image.location = _req.protocol + '://' + _req.headers.host + '/' + image.location;
		}

		image.hash = crypto.createHash('sha1').update(JSON.stringify(image)).digest('hex');

		async.waterfall([

			/**
			 * If the image already exists and it's within the TTL range use it, otherwise continue
			 */
			function (_callback) {
				var stat,
					createdAt = 0,
					now = new Date().getTime();

				try {
					stat = fs.statSync(config.cacheFolder + '/' + image.hash);
					createdAt = cast(stat.mtime, 'date').getTime();
				} catch(e) {};

				if(stat && now - createdAt < config.ttl && stat.size > 0) {

					var gmImage = gm(config.cacheFolder + '/' + image.hash)
						.options(gmOptions)
						.format({
							bufferStream: true
						}, function (_error, _format) {
							if(_error) {
								console.log(_error);
								return _callback(_error);
							}
							image.format = _format;
							if(!_res.headersSent) {
								_res.header('Content-Type', 'image/' + _format.toLowerCase());
							}
							gmImage.stream()
								.pipe(_res);
						});

				} else {
					_callback();
				}

			},

			/**
			 * Get the image
			 */
			function (_callback) {
				if(config.allowProxy) {
					var client = http;
					if(image.location.indexOf('https://') === 0) {
						client = https;
					}
					client.get(image.location, function (_httpResponse) {
						if(_httpResponse.statusCode >= 400) return _callback(new Error('status ' + _httpResponse.statusCode));
						_callback(null, _httpResponse);
					}).on('error', function (_error) {
						_callback(_error);
					});
				} else {
					var imageStream = fs.createReadStream(config.imageDir + image.location);
					_callback(null, imageStream);
				}
			},

			/**
			 * Perform image resize/crop operations
			 */
			function (_imageSrc, _manipulationDoneCallback) {
				var gmImage = gm(_imageSrc, image.hash).options(gmOptions);

				async.waterfall([

					//Get original size
					function (_callback) {
						gmImage.size({
							bufferStream: true
						}, function (_error, _size) {
							if(_error) {
								console.log(_error);
								return _callback(_error);
							}
							image.size = _size;

							_callback(null);
						});
					},

					//Get original content-type
					function (_callback) {
						gmImage.format({
							bufferStream: true
						}, function (_error, _format) {
							if(_error) {
								console.log(_error);
								return _callback(_error);
							}
							image.format = _format;
							if(!_res.headersSent) {
								_res.header('Content-Type', 'image/' + _format.toLowerCase());
							}

							_callback(null);
						});
					},

					// Crop
					function (_callback) {
						// If a crop ratio has been specified
						if(!(!image.crop.width && !image.crop.height)) {

							var newSize = {
								width: image.size.width,
								height: image.size.height
							};
							var offset = {
								x: 0,
								y: 0
							};

							var sourceRatio = image.size.width / image.size.height;
							var targetRatio = image.crop.width / image.crop.height;

							if(sourceRatio < targetRatio) {
								newSize.height = image.size.width / targetRatio;
							} else if(sourceRatio > targetRatio) {
								newSize.width = image.size.height * targetRatio;
							} else {
								//Matching ratios. dont need to do anything.
								return _callback(null);
							}

							offset.x = (image.size.width - newSize.width) / 2;
							offset.y = (image.size.height - newSize.height) / 2;

							gmImage.crop(
								newSize.width,
								newSize.height,
								offset.x,
								offset.y
							);
						}
						_callback(null);
					},

					// Resize
					function (_callback) {
						// If a width or height has been sepcified
						if(!(!image.resize.width && !image.resize.height)) {
							gmImage.resize(image.resize.width, image.resize.height, image.upscale === true ? '' : '>');
						}
						_callback(null);
					},

					// Quality
					function (_callback) {
						if(typeof image.quality === 'number') {
							gmImage.quality(image.quality);
						}
						_callback();
					}

				], function (_error) {

					//Stream it back.
					gmImage.autoOrient().stream(function (_error, _stdout, _stderr) {
						if(_error) {
							console.log(_error);
							return _manipulationDoneCallback(_error);
						}

						var writeStream = fs.createWriteStream(config.cacheFolder + '/' + image.hash);

						// Pipe to the response
						_stdout.pipe(_res);

						// Pipe to the cache folder
						_stdout.pipe(writeStream);

						//Close up the waterfall when done
						_stdout.on('end', function () {
							_manipulationDoneCallback(null);
						})
					});
				});

			}

		], function (_error) {
			if(_error) {
				console.log('error', _error);
				_next(_error);
			}
		});

	}
}
<commit_msg>Responds with a nice error if the content type isnt supported<commit_after>var _ = require('underscore'),
	async = require('async'),
	cast = require('sc-cast'),
	crypto = require('crypto'),
	fs = require('fs'),
	os = require('os'),
	gm = require('gm'),
	https = require('https'),
	http = require('http');

module.exports = function (_config) {
	var config = _.extend({

		cacheFolder: os.tmpdir(),
		ttl: 1000 * 60 * 60 * 24 * 7, // 1 week
		allowProxy: true,
		imageDir: process.cwd(),

	}, _config);

	return function (_req, _res, _next) {
		var dimensions = _req.query.resize || '0x0',
			crop = _req.query.crop || '0x0',
			quality = _req.query.quality;

		var gmOptions = {};
		if(config.imageMagick) {
			gmOptions.imageMagick = config.imageMagick;
		}
		if(config.graphicsMagick) {
			gmOptions.graphicsMagick = config.graphicsMagick;
		}

		var image = {
			query: JSON.stringify(_req.query),
			location: _req.query.image,
			resize: {
				width: cast(_.first(dimensions.match(/^[^x]+/)), 'number') || null,
				height: cast(_.first(dimensions.match(/[^x]+$/)), 'number') || null
			},
			crop: {
				width: cast(_.first(crop.match(/^[^x]+/)), 'number') || null,
				height: cast(_.first(crop.match(/[^x]+$/)), 'number') || null
			},
			size: {
				width: 0,
				height: 0
			},
			quality: cast(quality, 'number'),
			upscale: /true/i.test(_req.query.upscale)
		};

		if(config.allowProxy && !/^https?\:/.test(image.location)) {
			image.location = image.location.trim().replace(/^\//, '');
			image.location = _req.protocol + '://' + _req.headers.host + '/' + image.location;
		}

		image.hash = crypto.createHash('sha1').update(JSON.stringify(image)).digest('hex');

		async.waterfall([

			/**
			 * If the image already exists and it's within the TTL range use it, otherwise continue
			 */
			function (_callback) {
				var stat,
					createdAt = 0,
					now = new Date().getTime();

				try {
					stat = fs.statSync(config.cacheFolder + '/' + image.hash);
					createdAt = cast(stat.mtime, 'date').getTime();
				} catch(e) {};

				if(stat && now - createdAt < config.ttl && stat.size > 0) {

					var gmImage = gm(config.cacheFolder + '/' + image.hash)
						.options(gmOptions)
						.format({
							bufferStream: true
						}, function (_error, _format) {
							if(_error) {
								console.log(_error);
								return _callback(_error);
							}
							image.format = _format;
							if(!_res.headersSent) {
								_res.header('Content-Type', 'image/' + _format.toLowerCase());
							}
							gmImage.stream()
								.pipe(_res);
						});

				} else {
					_callback();
				}

			},

			/**
			 * Get the image
			 */
			function (_callback) {
				if(config.allowProxy) {
					var client = http;
					if(image.location.indexOf('https://') === 0) {
						client = https;
					}
					client.get(image.location, function (_httpResponse) {
						if(_httpResponse.statusCode >= 400) return _callback(new Error('status ' + _httpResponse.statusCode));
						_callback(null, _httpResponse);
					}).on('error', function (_error) {
						_callback(_error);
					});
				} else {
					var imageStream = fs.createReadStream(config.imageDir + image.location);
					_callback(null, imageStream);
				}
			},

			/**
			 * Perform image resize/crop operations
			 */
			function (_imageSrc, _manipulationDoneCallback) {
				var gmImage = gm(_imageSrc, image.hash).options(gmOptions);

				async.waterfall([

					//Get original size
					function (_callback) {
						gmImage.size({
							bufferStream: true
						}, function (_error, _size) {
							if(_error) {
								return _callback(_error);
							}
							image.size = _size;

							_callback(null);
						});
					},

					//Get original content-type
					function (_callback) {
						gmImage.format({
							bufferStream: true
						}, function (_error, _format) {
							if(_error) {
								console.log(_error);
								return _callback(_error);
							}
							image.format = _format;
							if(!_res.headersSent) {
								_res.header('Content-Type', 'image/' + _format.toLowerCase());
							}

							_callback(null);
						});
					},

					// Crop
					function (_callback) {
						// If a crop ratio has been specified
						if(!(!image.crop.width && !image.crop.height)) {

							var newSize = {
								width: image.size.width,
								height: image.size.height
							};
							var offset = {
								x: 0,
								y: 0
							};

							var sourceRatio = image.size.width / image.size.height;
							var targetRatio = image.crop.width / image.crop.height;

							if(sourceRatio < targetRatio) {
								newSize.height = image.size.width / targetRatio;
							} else if(sourceRatio > targetRatio) {
								newSize.width = image.size.height * targetRatio;
							} else {
								//Matching ratios. dont need to do anything.
								return _callback(null);
							}

							offset.x = (image.size.width - newSize.width) / 2;
							offset.y = (image.size.height - newSize.height) / 2;

							gmImage.crop(
								newSize.width,
								newSize.height,
								offset.x,
								offset.y
							);
						}
						_callback(null);
					},

					// Resize
					function (_callback) {
						// If a width or height has been sepcified
						if(!(!image.resize.width && !image.resize.height)) {
							gmImage.resize(image.resize.width, image.resize.height, image.upscale === true ? '' : '>');
						}
						_callback(null);
					},

					// Quality
					function (_callback) {
						if(typeof image.quality === 'number') {
							gmImage.quality(image.quality);
						}
						_callback();
					}

				], function (_error) {

					if (_error) return _manipulationDoneCallback(_error);

					//Stream it back.
					gmImage.autoOrient().stream(function (_error, _stdout, _stderr) {
						if(_error) {
							console.log(_error);
							return _manipulationDoneCallback(_error);
						}

						var writeStream = fs.createWriteStream(config.cacheFolder + '/' + image.hash);

						// Pipe to the response
						_stdout.pipe(_res);

						// Pipe to the cache folder
						_stdout.pipe(writeStream);

						//Close up the waterfall when done
						_stdout.on('end', function () {
							_manipulationDoneCallback(null);
						})
					});
				});

			}

		], function (_error) {
			if(_error) {
				if (_error.message.indexOf('no decode delegate') !== -1) {
					_res.status(415).send({
						error: {
							status: 415,
							message: 'Unsupported file format'
						}
					});
				} else {
					_next(_error);
				}
			}
		});

	}
}
<|endoftext|>


<commit_before>/* global window:true */
'use strict';

var React = require('react');
var tweenState = require('react-tween-state');
var merge = require('lodash.merge');
var clone = require('lodash.clone');
var Draggable = React.createFactory(require('react-draggable'));

function getRotationAngle(v, max, angle) {
  return angle * (v / max);
}

function rotate(deg) {
  var v = 'rotate('+deg+'deg)';
  return {
    transform: v,
    webkitTransform: v,
    mozTransform: v,
    oTransform: v,
    msTransform: v
  };
}

// TODO: rotate back if stopped and didnt swipe right or left

var Swipeable = React.createClass({
  displayName: 'Swipeable',
  mixins: [tweenState.Mixin],
  propTypes: {
    onDragStart: React.PropTypes.func,
    onDragStop: React.PropTypes.func,
    onDrag: React.PropTypes.func,
    onSwipeRight: React.PropTypes.func,
    onSwipeLeft: React.PropTypes.func,
    zIndex: React.PropTypes.number,
    rotationAngle: React.PropTypes.number,
    animation: React.PropTypes.object
  },

  getDefaultProps: function(){
    return {
      rotationAngle: 20,
      animation: {
        easing: tweenState.easingTypes.easeInElastic,
        duration: 750,
        endValue: 0
      }
    };
  },

  getInitialState: function(){
    return {
      rotation: 0,
      swiped: null
    };
  },

  componentDidMount: function(){
    this.setBreakPoint();
    window.addEventListener('resize', this.setBreakPoint);
  },

  componentWillUnmount: function() {
    window.removeEventListener('resize', this.setBreakPoint);
  },

  setBreakPoint: function(){
    var el = this.getDOMNode();
    var breakpoint = el.offsetWidth / 2;
    if (this.state.breakpoint !== breakpoint) {
      this.setState({breakpoint: breakpoint});
    }
  },

  componentDidUpdate: function(){
    this.setBreakPoint();
  },

  handleDrag: function(event, ui){
    if (this.state.swiped) {
      return;
    }

    var pos = ui.position.left;
    var rotateAngle = getRotationAngle(pos, this.state.breakpoint, this.props.rotationAngle);
    this.setState({rotation: rotateAngle});

    if (this.props.onDrag) {
      this.props.onDrag(event, ui);
    }
  },

  handleDragStop: function(event, ui){
    if (this.state.swiped) {
      return;
    }

    var pos = ui.position.left;

    if (pos >= this.state.breakpoint) {
      this.reset();
      this.setState({swiped: 'right'}, this.props.onSwipeRight);
    } else if (pos <= -this.state.breakpoint) {
      this.reset();
      this.setState({swiped: 'left'}, this.props.onSwipeLeft);
    }

    if (!this.state.swiped &&
      ui.position.left !== this.state.breakpoint &&
      ui.position.left !== -this.state.breakpoint) {
      this.reset();
    }

    if (this.props.onDragStop) {
      this.props.onDragStop(event, ui);
    }
  },

  reset: function(){
    if (this.props.animation) {
      this.tweenState('rotation', clone(this.props.animation));
    } else {
      this.setState({rotation: 0});
    }
    this.refs.draggable.reset(clone(this.props.animation), clone(this.props.animation));
  },

  render: function(){
    var defaultStyle = {
      position: 'relative',
      userSelect: 'none',
      webkitUserSelect: 'none',
      mozUserSelect: 'none',
      msUserSelect: 'none',
      oUserSelect: 'none',
    };
    var style = merge(defaultStyle, rotate(this.getTweeningValue('rotation')));
    var axis = (this.state.swiped ? null : 'both');

    var draggable = Draggable({
      ref: 'draggable',
      axis: axis,
      onStart: this.props.onDragStart,
      onStop: this.handleDragStop,
      onDrag: this.handleDrag,
      zIndex: this.props.zIndex,
      ranges: {
        x: [-this.state.breakpoint, this.state.breakpoint]
      },
      style: style,
      className: this.props.className
    }, this.props.children);

    return draggable;
  }
});

module.exports = Swipeable;<commit_msg>make it more like tinder<commit_after>/* global window:true */
'use strict';

var React = require('react');
var tweenState = require('react-tween-state');
var merge = require('lodash.merge');
var clone = require('lodash.clone');
var Draggable = React.createFactory(require('react-draggable'));

function getRotationAngle(v, max, angle) {
  return angle * (v / max);
}

function rotate(deg) {
  var v = 'rotate('+deg+'deg)';
  return {
    transform: v,
    webkitTransform: v,
    mozTransform: v,
    oTransform: v,
    msTransform: v
  };
}

// TODO: rotate back if stopped and didnt swipe right or left

var Swipeable = React.createClass({
  displayName: 'Swipeable',
  mixins: [tweenState.Mixin],
  propTypes: {
    onDragStart: React.PropTypes.func,
    onDragStop: React.PropTypes.func,
    onDrag: React.PropTypes.func,
    onSwipeRight: React.PropTypes.func,
    onSwipeLeft: React.PropTypes.func,
    zIndex: React.PropTypes.number,
    rotationAngle: React.PropTypes.number,
    animation: React.PropTypes.object
  },

  getDefaultProps: function(){
    return {
      rotationAngle: 20,
      animation: {
        easing: tweenState.easingTypes.easeOutElastic,
        duration: 750,
        endValue: 0
      }
    };
  },

  getInitialState: function(){
    return {
      rotation: 0,
      swiped: null
    };
  },

  componentDidMount: function(){
    this.setBreakPoint();
    window.addEventListener('resize', this.setBreakPoint);
  },

  componentWillUnmount: function() {
    window.removeEventListener('resize', this.setBreakPoint);
  },

  setBreakPoint: function(){
    var el = this.getDOMNode();
    var breakpoint = el.offsetWidth / 2;
    if (this.state.breakpoint !== breakpoint) {
      this.setState({breakpoint: breakpoint});
    }
  },

  componentDidUpdate: function(){
    this.setBreakPoint();
  },

  handleDrag: function(event, ui){
    if (this.state.swiped) {
      return;
    }

    var pos = ui.position.left;
    var rotateAngle = getRotationAngle(pos, this.state.breakpoint, this.props.rotationAngle);
    this.setState({rotation: rotateAngle});

    if (this.props.onDrag) {
      this.props.onDrag(event, ui);
    }
  },

  handleDragStop: function(event, ui){
    if (this.state.swiped) {
      return;
    }

    var pos = ui.position.left;

    if (pos >= this.state.breakpoint) {
      this.reset();
      this.setState({swiped: 'right'}, this.props.onSwipeRight);
    } else if (pos <= -this.state.breakpoint) {
      this.reset();
      this.setState({swiped: 'left'}, this.props.onSwipeLeft);
    }

    if (!this.state.swiped &&
      ui.position.left !== this.state.breakpoint &&
      ui.position.left !== -this.state.breakpoint) {
      this.reset();
    }

    if (this.props.onDragStop) {
      this.props.onDragStop(event, ui);
    }
  },

  reset: function(){
    if (this.props.animation) {
      this.tweenState('rotation', clone(this.props.animation));
    } else {
      this.setState({rotation: 0});
    }
    this.refs.draggable.reset(clone(this.props.animation), clone(this.props.animation));
  },

  render: function(){
    var defaultStyle = {
      position: 'relative',
      userSelect: 'none',
      webkitUserSelect: 'none',
      mozUserSelect: 'none',
      msUserSelect: 'none',
      oUserSelect: 'none',
    };
    var style = merge(defaultStyle, rotate(this.getTweeningValue('rotation')));
    var axis = (this.state.swiped ? null : 'both');

    var draggable = Draggable({
      ref: 'draggable',
      axis: axis,
      onStart: this.props.onDragStart,
      onStop: this.handleDragStop,
      onDrag: this.handleDrag,
      zIndex: this.props.zIndex,
      ranges: {
        x: [-this.state.breakpoint, this.state.breakpoint]
      },
      style: style,
      className: this.props.className
    }, this.props.children);

    return draggable;
  }
});

module.exports = Swipeable;<|endoftext|>


<commit_before>import optimize from 'optimize-js'

export default (options = {}) => {
  return {
    name: 'optimize-js',
    ongenerate (bundle, output) {
      // attempt to hack around optimize-js inline sourcemaps, meh
      // const raw = optimize(output.code, { sourceMap: true })
      // const split = raw.split('//# sourceMappingURL=data:application/json;charset=utf-8;base64,')
      // const result = { code: split[0] }
      // result.map = JSON.parse(Buffer.from(split[1], 'base64'))

      // more accurate sourcemaps, todo: fix, PR optimize-js
      const raw = optimize(output.code, { sourceMap: false })
      const result = { code: raw, map: output.map }
      return result
    }
  }
}
<commit_msg>use correct hook<commit_after>import optimize from 'optimize-js'

export default (options = {}) => {
  return {
    name: 'optimize-js',
    transformBundle: function transformBundle (code) {
      // hack around optimize-js inline sourcemaps, meh
      const raw = optimize(code, { sourceMap: true })
      const split = raw.split('//# sourceMappingURL=data:application/json;charset=utf-8;base64,')
      const result = { code: split[0] }
      result.map = JSON.parse(Buffer.from(split[1], 'base64'))
      return result
    }
  }
}
<|endoftext|>