<commit_before>'use strict';

var React = require('react');
var classNames = require('classnames');
var ClassNameMixin = require('./mixins/ClassNameMixin');
var TransitionEvents = require('./utils/TransitionEvents');

React.initializeTouchEvents(true);

var Slider = React.createClass({
  mixins: [ClassNameMixin],

  propTypes: {
    theme: React.PropTypes.oneOf(['default', 'a1', 'a2', 'a3', 'a4', 'a5',
      'b1', 'b2', 'b3', 'b4', 'c1', 'c2', 'c3', 'c4', 'd1', 'd2', 'd3']),
    directionNav: React.PropTypes.bool,   // prev/next icon
    controlNav: React.PropTypes.bool,

    animation: React.PropTypes.string,    // not working
    slide: React.PropTypes.bool,
    autoPlay: React.PropTypes.bool,
    slideSpeed: React.PropTypes.number,   // interval
    loop: React.PropTypes.bool,           // loop slide

    pauseOnHover: React.PropTypes.bool,
    touch: React.PropTypes.bool,          // TODO: add touch support

    onSelect: React.PropTypes.func,
    onSlideEnd: React.PropTypes.func,
    activeIndex: React.PropTypes.number,
    defaultActiveIndex: React.PropTypes.number,
    direction: React.PropTypes.oneOf(['prev', 'next'])
  },

  getDefaultProps: function() {
    return {
      classPrefix: 'slider',
      theme: 'default',
      directionNav: true,
      controlNav: true,
      slide: true,
      autoPlay: true,
      loop: true,
      slideSpeed: 5000,
      pauseOnHover: true
    };
  },

  getInitialState: function() {
    return {
      activeIndex: this.props.defaultActiveIndex == null ?
        0 : this.props.defaultActiveIndex,
      previousActiveIndex: null,
      direction: null
    };
  },

  componentWillReceiveProps: function(nextProps) {
    var activeIndex = this.getActiveIndex();

    if (nextProps.activeIndex != null &&
      nextProps.activeIndex !== activeIndex) {
      clearTimeout(this.timeout);
      this.setState({
        previousActiveIndex: activeIndex,
        direction: nextProps.direction != null ? nextProps.direction :
          this.getDirection(activeIndex, nextProps.activeIndex)
      });
    }
  },

  componentDidMount: function() {
    this.props.autoPlay && this.waitForNext();
  },

  componentWillUnmount: function() {
    clearTimeout(this.timeout);
  },

  getDirection: function(prevIndex, index) {
    if (prevIndex === index) {
      return null;
    }

    return prevIndex > index ? 'prev' : 'next';
  },

  next: function(e) {
    e && e.preventDefault();

    var index = this.getActiveIndex() + 1;
    var count = React.Children.count(this.props.children);

    if (index > count - 1) {
      if (!this.props.loop) {
        return;
      }
      index = 0;
    }

    this.handleSelect(index, 'next');
  },

  prev: function(e) {
    e && e.preventDefault();

    var index = this.getActiveIndex() - 1;

    if (index < 0) {
      if (!this.props.loop) {
        return;
      }
      index = React.Children.count(this.props.children) - 1;
    }

    this.handleSelect(index, 'prev');
  },

  pause: function() {
    this.isPaused = true;
    clearTimeout(this.timeout);
  },

  play: function() {
    this.isPaused = false;
    this.waitForNext();
  },

  waitForNext: function() {
    if (!this.isPaused && this.props.slide && this.props.slideSpeed &&
      this.props.activeIndex == null) {
      this.timeout = setTimeout(this.next, this.props.slideSpeed);
    }
  },

  handleMouseOver: function() {
    if (this.props.pauseOnHover) {
      this.pause();
    }
  },

  handleMouseOut: function() {
    if (this.isPaused) {
      this.play();
    }
  },

  getActiveIndex: function() {
    return this.props.activeIndex != null ?
      this.props.activeIndex : this.state.activeIndex;
  },

  handleItemAnimateOutEnd: function() {
    this.setState({
      previousActiveIndex: null,
      direction: null
    }, function() {
      this.waitForNext();

      if (this.props.onSlideEnd) {
        this.props.onSlideEnd();
      }
    });
  },

  handleSelect: function(index, direction, e) {
    e && e.preventDefault();
    clearTimeout(this.timeout);

    var previousActiveIndex = this.getActiveIndex();

    direction = direction || this.getDirection(previousActiveIndex, index);

    if (this.props.onSelect) {
      this.props.onSelect(index, direction);
    }

    if (this.props.activeIndex == null && index !== previousActiveIndex) {
      if (this.state.previousActiveIndex != null) {
        // If currently animating don't activate the new index.
        // TODO: look into queuing this canceled call and
        // animating after the current animation has ended.
        return;
      }

      this.setState({
        activeIndex: index,
        previousActiveIndex: previousActiveIndex,
        direction: direction
      });
    }
  },

  renderDirectionNav: function() {
    return this.props.directionNav ? (

            Previous

            Next

    ) : null;
  },

  renderControlNav: function() {
    if (this.props.controlNav) {
      var isThumbnailNav = false;
      var children = React.Children.map(this.props.children,
        function(child, i) {
        var className = (i === this.getActiveIndex()) ?
          this.setClassNamespace('active') : null;

        if (!isThumbnailNav) {
          isThumbnailNav = !!child.props.thumbnail;
        }

        var thumb = child.props.thumbnail;

        return (

            {thumb ? (

            ) : (
              )}

        );
      }.bind(this));
      var controlClass = this.setClassNamespace('control-' +
        (isThumbnailNav ? 'thumbs' : 'paging'));

      return (

          {children}

      );
    }

    return null;
  },

  renderItem: function(child, index) {
    var activeIndex = this.getActiveIndex();
    var isActive = (index === activeIndex);
    var isPreviousActive = this.state.previousActiveIndex != null &&
      this.state.previousActiveIndex === index && this.props.slide;

    return React.cloneElement(
      child,
      {
        active: isActive,
        ref: child.ref,
        key: child.key ? child.key : index,
        index: index,
        animateOut: isPreviousActive,
        animateIn: isActive && this.state.previousActiveIndex != null &&
          this.props.slide,
        direction: this.state.direction,
        onAnimateOutEnd: isPreviousActive ? this.handleItemAnimateOutEnd : null
      }
    );
  },

  render: function() {
    var classSet = this.getClassSet();
    var viewportStyle = {
      overflow: 'hidden',
      position: 'relative',
      width: '100%'
    };

    // React version slider style
    classSet[this.prefixClass('slide')] = true;

    return (

            {React.Children.map(this.props.children, this.renderItem)}

        {this.renderDirectionNav()}
        {this.renderControlNav()}

    );
  }
});

Slider.Item = React.createClass({
  propTypes: {
    direction: React.PropTypes.oneOf(['prev', 'next']),
    onAnimateOutEnd: React.PropTypes.func,
    active: React.PropTypes.bool,
    animateIn: React.PropTypes.bool,
    animateOut: React.PropTypes.bool,
    caption: React.PropTypes.node,
    index: React.PropTypes.number,
    thumbnail: React.PropTypes.string
  },

  getInitialState: function() {
    return {
      direction: null
    };
  },

  getDefaultProps: function() {
    return {
      animation: true
    };
  },

  componentWillReceiveProps: function(nextProps) {
    if (this.props.active !== nextProps.active) {
      this.setState({
        direction: null
      });
    }
  },

  componentDidUpdate: function(prevProps) {
    if (!this.props.active && prevProps.active) {
      TransitionEvents.on(React.findDOMNode(this), this.handleAnimateOutEnd);
    }

    if (this.props.active !== prevProps.active) {
      setTimeout(this.startAnimation, 20);
    }
  },

  handleAnimateOutEnd: function() {
    if (this.props.onAnimateOutEnd && this.isMounted()) {
      this.props.onAnimateOutEnd(this.props.index);
    }
  },

  startAnimation: function() {
    if (!this.isMounted()) {
      return;
    }

    this.setState({
      direction: this.props.direction === 'prev' ?
        'right' : 'left'
    });
  },

  render: function() {
    var classSet = {
      active: (this.props.active && !this.props.animateIn) ||
        this.props.animateOut,
      next: this.props.active && this.props.animateIn &&
        this.props.direction === 'next',
      prev: this.props.active && this.props.animateIn &&
        this.props.direction === 'prev'
    };

    if (this.state.direction && (this.props.animateIn ||
      this.props.animateOut)) {
      classSet[this.state.direction] = true;
    }

    return (

        {this.props.children}

    );
  }
});

module.exports = Slider;
<commit_msg>remove initializeTouchEvents(for react 0.14)<commit_after>'use strict';

var React = require('react');
var classNames = require('classnames');
var ClassNameMixin = require('./mixins/ClassNameMixin');
var TransitionEvents = require('./utils/TransitionEvents');

//React.initializeTouchEvents(true);

var Slider = React.createClass({
  mixins: [ClassNameMixin],

  propTypes: {
    theme: React.PropTypes.oneOf(['default', 'a1', 'a2', 'a3', 'a4', 'a5',
      'b1', 'b2', 'b3', 'b4', 'c1', 'c2', 'c3', 'c4', 'd1', 'd2', 'd3']),
    directionNav: React.PropTypes.bool,   // prev/next icon
    controlNav: React.PropTypes.bool,

    animation: React.PropTypes.string,    // not working
    slide: React.PropTypes.bool,
    autoPlay: React.PropTypes.bool,
    slideSpeed: React.PropTypes.number,   // interval
    loop: React.PropTypes.bool,           // loop slide

    pauseOnHover: React.PropTypes.bool,
    touch: React.PropTypes.bool,          // TODO: add touch support

    onSelect: React.PropTypes.func,
    onSlideEnd: React.PropTypes.func,
    activeIndex: React.PropTypes.number,
    defaultActiveIndex: React.PropTypes.number,
    direction: React.PropTypes.oneOf(['prev', 'next'])
  },

  getDefaultProps: function() {
    return {
      classPrefix: 'slider',
      theme: 'default',
      directionNav: true,
      controlNav: true,
      slide: true,
      autoPlay: true,
      loop: true,
      slideSpeed: 5000,
      pauseOnHover: true
    };
  },

  getInitialState: function() {
    return {
      activeIndex: this.props.defaultActiveIndex == null ?
        0 : this.props.defaultActiveIndex,
      previousActiveIndex: null,
      direction: null
    };
  },

  componentWillReceiveProps: function(nextProps) {
    var activeIndex = this.getActiveIndex();

    if (nextProps.activeIndex != null &&
      nextProps.activeIndex !== activeIndex) {
      clearTimeout(this.timeout);
      this.setState({
        previousActiveIndex: activeIndex,
        direction: nextProps.direction != null ? nextProps.direction :
          this.getDirection(activeIndex, nextProps.activeIndex)
      });
    }
  },

  componentDidMount: function() {
    this.props.autoPlay && this.waitForNext();
  },

  componentWillUnmount: function() {
    clearTimeout(this.timeout);
  },

  getDirection: function(prevIndex, index) {
    if (prevIndex === index) {
      return null;
    }

    return prevIndex > index ? 'prev' : 'next';
  },

  next: function(e) {
    e && e.preventDefault();

    var index = this.getActiveIndex() + 1;
    var count = React.Children.count(this.props.children);

    if (index > count - 1) {
      if (!this.props.loop) {
        return;
      }
      index = 0;
    }

    this.handleSelect(index, 'next');
  },

  prev: function(e) {
    e && e.preventDefault();

    var index = this.getActiveIndex() - 1;

    if (index < 0) {
      if (!this.props.loop) {
        return;
      }
      index = React.Children.count(this.props.children) - 1;
    }

    this.handleSelect(index, 'prev');
  },

  pause: function() {
    this.isPaused = true;
    clearTimeout(this.timeout);
  },

  play: function() {
    this.isPaused = false;
    this.waitForNext();
  },

  waitForNext: function() {
    if (!this.isPaused && this.props.slide && this.props.slideSpeed &&
      this.props.activeIndex == null) {
      this.timeout = setTimeout(this.next, this.props.slideSpeed);
    }
  },

  handleMouseOver: function() {
    if (this.props.pauseOnHover) {
      this.pause();
    }
  },

  handleMouseOut: function() {
    if (this.isPaused) {
      this.play();
    }
  },

  getActiveIndex: function() {
    return this.props.activeIndex != null ?
      this.props.activeIndex : this.state.activeIndex;
  },

  handleItemAnimateOutEnd: function() {
    this.setState({
      previousActiveIndex: null,
      direction: null
    }, function() {
      this.waitForNext();

      if (this.props.onSlideEnd) {
        this.props.onSlideEnd();
      }
    });
  },

  handleSelect: function(index, direction, e) {
    e && e.preventDefault();
    clearTimeout(this.timeout);

    var previousActiveIndex = this.getActiveIndex();

    direction = direction || this.getDirection(previousActiveIndex, index);

    if (this.props.onSelect) {
      this.props.onSelect(index, direction);
    }

    if (this.props.activeIndex == null && index !== previousActiveIndex) {
      if (this.state.previousActiveIndex != null) {
        // If currently animating don't activate the new index.
        // TODO: look into queuing this canceled call and
        // animating after the current animation has ended.
        return;
      }

      this.setState({
        activeIndex: index,
        previousActiveIndex: previousActiveIndex,
        direction: direction
      });
    }
  },

  renderDirectionNav: function() {
    return this.props.directionNav ? (

            Previous

            Next

    ) : null;
  },

  renderControlNav: function() {
    if (this.props.controlNav) {
      var isThumbnailNav = false;
      var children = React.Children.map(this.props.children,
        function(child, i) {
        var className = (i === this.getActiveIndex()) ?
          this.setClassNamespace('active') : null;

        if (!isThumbnailNav) {
          isThumbnailNav = !!child.props.thumbnail;
        }

        var thumb = child.props.thumbnail;

        return (

            {thumb ? (

            ) : (
              )}

        );
      }.bind(this));
      var controlClass = this.setClassNamespace('control-' +
        (isThumbnailNav ? 'thumbs' : 'paging'));

      return (

          {children}

      );
    }

    return null;
  },

  renderItem: function(child, index) {
    var activeIndex = this.getActiveIndex();
    var isActive = (index === activeIndex);
    var isPreviousActive = this.state.previousActiveIndex != null &&
      this.state.previousActiveIndex === index && this.props.slide;

    return React.cloneElement(
      child,
      {
        active: isActive,
        ref: child.ref,
        key: child.key ? child.key : index,
        index: index,
        animateOut: isPreviousActive,
        animateIn: isActive && this.state.previousActiveIndex != null &&
          this.props.slide,
        direction: this.state.direction,
        onAnimateOutEnd: isPreviousActive ? this.handleItemAnimateOutEnd : null
      }
    );
  },

  render: function() {
    var classSet = this.getClassSet();
    var viewportStyle = {
      overflow: 'hidden',
      position: 'relative',
      width: '100%'
    };

    // React version slider style
    classSet[this.prefixClass('slide')] = true;

    return (

            {React.Children.map(this.props.children, this.renderItem)}

        {this.renderDirectionNav()}
        {this.renderControlNav()}

    );
  }
});

Slider.Item = React.createClass({
  propTypes: {
    direction: React.PropTypes.oneOf(['prev', 'next']),
    onAnimateOutEnd: React.PropTypes.func,
    active: React.PropTypes.bool,
    animateIn: React.PropTypes.bool,
    animateOut: React.PropTypes.bool,
    caption: React.PropTypes.node,
    index: React.PropTypes.number,
    thumbnail: React.PropTypes.string
  },

  getInitialState: function() {
    return {
      direction: null
    };
  },

  getDefaultProps: function() {
    return {
      animation: true
    };
  },

  componentWillReceiveProps: function(nextProps) {
    if (this.props.active !== nextProps.active) {
      this.setState({
        direction: null
      });
    }
  },

  componentDidUpdate: function(prevProps) {
    if (!this.props.active && prevProps.active) {
      TransitionEvents.on(React.findDOMNode(this), this.handleAnimateOutEnd);
    }

    if (this.props.active !== prevProps.active) {
      setTimeout(this.startAnimation, 20);
    }
  },

  handleAnimateOutEnd: function() {
    if (this.props.onAnimateOutEnd && this.isMounted()) {
      this.props.onAnimateOutEnd(this.props.index);
    }
  },

  startAnimation: function() {
    if (!this.isMounted()) {
      return;
    }

    this.setState({
      direction: this.props.direction === 'prev' ?
        'right' : 'left'
    });
  },

  render: function() {
    var classSet = {
      active: (this.props.active && !this.props.animateIn) ||
        this.props.animateOut,
      next: this.props.active && this.props.animateIn &&
        this.props.direction === 'next',
      prev: this.props.active && this.props.animateIn &&
        this.props.direction === 'prev'
    };

    if (this.state.direction && (this.props.animateIn ||
      this.props.animateOut)) {
      classSet[this.state.direction] = true;
    }

    return (

        {this.props.children}

    );
  }
});

module.exports = Slider;
<|endoftext|>


<commit_before>(function (exports) {

    function debug (d) {
        console.log("DEBUG: " + d);
    };

    function EchidnaPublisher ($publish_form, api_server) {
        var self = this;

        self.api_server = api_server;
        self.$publish_form = $publish_form;

        self.init = function () {
            var btn = self.$publish_form.find(".echidna-publish-btn");
            btn.on("click", self.on_publish);
        };

        self.post = function (channel, msg) {
            debug("Publishing to " + channel + " ...");
            debug(JSON.stringify(msg));

            var xhdr = $.post(
                "http://" + self.api_server + "/publish/" + channel + "/",
                JSON.stringify(msg)
            ).done(function (data, status) {
                debug("Published successfully.");
            }).fail(function () {
                debug("Publishing failed. :/");
            });
        };

        self.on_publish = function () {
            var text_input = self.$publish_form.find(".echidna-publish-text");
            var channel_input = self.$publish_form.find(
                ".echidna-publish-channels :checked");

            var text = text_input.val().trim(),
                channel = channel_input.val().trim(),
                msg = null;

            if (text) {
                msg = {
                    created: $.now(),
                    text: text,
                }
                self.post(channel, msg);
            }

            text_input.val("");
        };

        self.init();
    }

    function EchidnaApi (api_server, opts) {
        var self = this;

        self.api_server = api_server;
        self.callbacks = opts.callbacks || {};

        self.socket = null;

        self.init = function () {
            var socket = new WebSocket("ws://" + self.api_server + "/subscribe");
            self.socket = socket;
            socket.onopen = self.ws.on_open;
            socket.onclose = self.ws.on_close;
            socket.onmessage = self.ws.on_message;
            socket.onerror = self.ws.on_error;
        };

        self.callback = function () {
            var name = Array.prototype.shift.call(arguments);
            if (self.callbacks[name]) {
                self.callbacks[name].apply(self, arguments);
            };
        };

        self.ws = {};

        self.ws.on_open = function () {
            debug("connected");
            self.callback('on_open');
        };

        self.ws.on_close = function () {
            debug("disconnected");
            self.callback('on_close');
        };

        self.ws.on_message = function (event) {
            debug("received: " + event.data);
            var msg = JSON.parse(event.data);
            var callback_name = "handle_" + msg.msg_type;
            self.callback(callback_name, msg);
        };

        self.ws.on_error = function (e) {
            debug(e);
            self.callback('on_error', e);
        };

        self.send_msg = function (msg) {
            self.socket.send(JSON.stringify(msg));
        };

        self.subscribe = function (channel) {
            self.send_msg({
                "msg_type": "subscribe",
                "channel": channel,
            });
        };

        self.unsubscribe = function (channel) {
            self.send_msg({
                "msg_type": "unsubscribe",
                "channel": channel,
            });
        };

        self.init();
    }

    function EchidnaReceiver ($receive_form, $msg_list, api_server) {
        var self = this;

        self.$receive_form = $receive_form;
        self.$channel_boxes = $receive_form.find("input[type=checkbox]");
        self.$msg_list = $msg_list;
        self.$no_cards_li = $msg_list.find(".echidna-no-cards");
        self.api_server = api_server;

        self.api = null;
        self.channels = {};

        self.init = function () {
            self.api = new EchidnaApi(self.api_server, {
                "callbacks": {
                    "on_open": self.on_open,
                    "handle_card": self.handle_card,
                    "handle_error": self.handle_error
                }
            });
            self.$channel_boxes.on("click", self.update_channels);
        };

        self.update_channels = function () {
            self.$channel_boxes.each(function (idx, elem) {
                var channel = elem.value;
                if (elem.checked && !self.channels[channel]) {
                    self.add_channel(channel);
                }
                else if (!elem.checked && self.channels[channel]) {
                    self.remove_channel(channel);
                    self.remove_channel_msgs(channel);
                }
            });
        };

        self.add_channel = function (channel) {
            debug("Adding channel " + channel + " ...");
            self.channels[channel] = true;
            self.api.subscribe(channel);
        };

        self.remove_channel = function (channel) {
            debug("Removing channel " + channel + " ...");
            self.channels[channel] = false;
            self.api.unsubscribe(channel);
        };

        self.remove_channel_msgs = function (channel) {
            self.check_no_cards_li();
        };

        self.check_no_cards_li = function () {
            msg_count = self.$msg_list.find("li").length;
            if (msg_count == 0) {
                self.$no_cards_li.show();
            }
            else if (msg_count > 1) {
                self.$no_cards_li.hide();
            }
        };

        self.on_open = function () {
            self.update_channels();
        };

        self.handle_card = function (msg) {
            var card = msg.card;
            var channel = msg.channel;
            var created = moment(card.created).format("MMMM Do YYYY, h:mm:ss a");
            self.$msg_list.prepend(
                '
' +
                    '' + created + '' +
                    '' + channel + '' +
                    card.text +
                    '
'
            );
            self.check_no_cards_li();
        };

        self.handle_error = function (msg) {
            debug("ERROR msg: " + JSON.stringify(msg));
        };

        self.init();
    }

    exports.EchidnaPublisher = EchidnaPublisher;
    exports.EchidnaApi = EchidnaApi;
    exports.EchidnaReceiver = EchidnaReceiver;

})(window.echidna = window.echidna || {});<commit_msg>Add removal of message on unsubscribe.<commit_after>(function (exports) {

    function debug (d) {
        console.log("DEBUG: " + d);
    };

    function EchidnaPublisher ($publish_form, api_server) {
        var self = this;

        self.api_server = api_server;
        self.$publish_form = $publish_form;

        self.init = function () {
            var btn = self.$publish_form.find(".echidna-publish-btn");
            btn.on("click", self.on_publish);
        };

        self.post = function (channel, msg) {
            debug("Publishing to " + channel + " ...");
            debug(JSON.stringify(msg));

            var xhdr = $.post(
                "http://" + self.api_server + "/publish/" + channel + "/",
                JSON.stringify(msg)
            ).done(function (data, status) {
                debug("Published successfully.");
            }).fail(function () {
                debug("Publishing failed. :/");
            });
        };

        self.on_publish = function () {
            var text_input = self.$publish_form.find(".echidna-publish-text");
            var channel_input = self.$publish_form.find(
                ".echidna-publish-channels :checked");

            var text = text_input.val().trim(),
                channel = channel_input.val().trim(),
                msg = null;

            if (text) {
                msg = {
                    created: $.now(),
                    text: text,
                }
                self.post(channel, msg);
            }

            text_input.val("");
        };

        self.init();
    }

    function EchidnaApi (api_server, opts) {
        var self = this;

        self.api_server = api_server;
        self.callbacks = opts.callbacks || {};

        self.socket = null;

        self.init = function () {
            var socket = new WebSocket("ws://" + self.api_server + "/subscribe");
            self.socket = socket;
            socket.onopen = self.ws.on_open;
            socket.onclose = self.ws.on_close;
            socket.onmessage = self.ws.on_message;
            socket.onerror = self.ws.on_error;
        };

        self.callback = function () {
            var name = Array.prototype.shift.call(arguments);
            if (self.callbacks[name]) {
                self.callbacks[name].apply(self, arguments);
            };
        };

        self.ws = {};

        self.ws.on_open = function () {
            debug("connected");
            self.callback('on_open');
        };

        self.ws.on_close = function () {
            debug("disconnected");
            self.callback('on_close');
        };

        self.ws.on_message = function (event) {
            debug("received: " + event.data);
            var msg = JSON.parse(event.data);
            var callback_name = "handle_" + msg.msg_type;
            self.callback(callback_name, msg);
        };

        self.ws.on_error = function (e) {
            debug(e);
            self.callback('on_error', e);
        };

        self.send_msg = function (msg) {
            self.socket.send(JSON.stringify(msg));
        };

        self.subscribe = function (channel) {
            self.send_msg({
                "msg_type": "subscribe",
                "channel": channel,
            });
        };

        self.unsubscribe = function (channel) {
            self.send_msg({
                "msg_type": "unsubscribe",
                "channel": channel,
            });
        };

        self.init();
    }

    function EchidnaReceiver ($receive_form, $msg_list, api_server) {
        var self = this;

        self.$receive_form = $receive_form;
        self.$channel_boxes = $receive_form.find("input[type=checkbox]");
        self.$msg_list = $msg_list;
        self.$no_cards_li = $msg_list.find(".echidna-no-cards");
        self.api_server = api_server;

        self.api = null;
        self.channels = {};

        self.init = function () {
            self.api = new EchidnaApi(self.api_server, {
                "callbacks": {
                    "on_open": self.on_open,
                    "handle_card": self.handle_card,
                    "handle_error": self.handle_error
                }
            });
            self.$channel_boxes.on("click", self.update_channels);
        };

        self.update_channels = function () {
            self.$channel_boxes.each(function (idx, elem) {
                var channel = elem.value;
                if (elem.checked && !self.channels[channel]) {
                    self.add_channel(channel);
                }
                else if (!elem.checked && self.channels[channel]) {
                    self.remove_channel(channel);
                }
            });
        };

        self.add_channel = function (channel) {
            debug("Adding channel " + channel + " ...");
            self.channels[channel] = true;
            self.api.subscribe(channel);
        };

        self.remove_channel = function (channel) {
            debug("Removing channel " + channel + " ...");
            self.channels[channel] = false;
            self.api.unsubscribe(channel);
            self.remove_channel_msgs(channel);
        };

        self.remove_channel_msgs = function (channel) {
            self.$msg_list.find("li[channel='" + channel + "']").remove();
            self.check_no_cards_li();
        };

        self.check_msg_overflow = function () {
            self.$msg_list.find("li:visible:gt(20)").remove();
        };

        self.check_no_cards_li = function () {
            msg_count = self.$msg_list.find("li:visible").length;
            debug(msg_count);
            if (msg_count == 0) {
                self.$no_cards_li.show();
            }
            else if (msg_count > 1) {
                self.$no_cards_li.hide();
            }
        };

        self.on_open = function () {
            self.update_channels();
        };

        self.handle_card = function (msg) {
            var card = msg.card;
            var channel = msg.channel;
            var created = moment(card.created).format("MMMM Do YYYY, h:mm:ss a");
            self.$msg_list.prepend(
                '
' +
                    '' + created + '' +
                    '' + channel + '' +
                    card.text +
                    '
'
            );
            self.check_msg_overflow();
            self.check_no_cards_li();
        };

        self.handle_error = function (msg) {
            debug("ERROR msg: " + JSON.stringify(msg));
        };

        self.init();
    }

    exports.EchidnaPublisher = EchidnaPublisher;
    exports.EchidnaApi = EchidnaApi;
    exports.EchidnaReceiver = EchidnaReceiver;

})(window.echidna = window.echidna || {});<|endoftext|>


<commit_before>var join = require('path').join
var basename = require('path').basename
var relative = require('path').relative
var semver = require('semver')
var normalizePath = require('normalize-path')
var relSymlink = require('../fs/rel_symlink')
var fs = require('mz/fs')
var mkdirp = require('../fs/mkdirp')
var debug = require('debug')('pnpm:link_bins')
var requireJson = require('../fs/require_json')
var binify = require('../binify')

var preserveSymlinks = semver.satisfies(process.version, '>=6.3.0')
var isWindows = process.platform === 'win32'

module.exports = linkAllBins
module.exports.linkPkgBins = linkPkgBins

function linkAllBins (modules) {
  getDirectories(modules)
    .reduce((pkgDirs, dir) => pkgDirs.concat(isScopedPkgsDir(dir) ? getDirectories(dir) : dir), [])
    .forEach(pkgDir => linkPkgBins(modules, pkgDir))
}

function getDirectories (srcPath) {
  return fs.readdirSync(srcPath)
    .map(relativePath => join(srcPath, relativePath))
    .filter(absolutePath => fs.statSync(absolutePath).isDirectory())
}

function isScopedPkgsDir (dirPath) {
  return basename(dirPath)[0] === '@'
}

/*
 * Links executable into `node_modules/.bin`.
 *
 * - `modules` (String) - the node_modules path
 * - `target` (String) - where the module is now; read package.json from here
 * - `fullname` (String) - fullname of the module (`rimraf@2.5.1`)
 *
 *     module = 'project/node_modules'
 *     target = 'project/node_modules/.store/rimraf@2.5.1'
 *     linkPkgBins(module, target)
 *
 *     // node_modules/.bin/rimraf -> ../.store/rimraf@2.5.1/cmd.js
 */

function linkPkgBins (modules, target) {
  var pkg = tryRequire(join(target, 'package.json'))

  if (!pkg || !pkg.bin) return

  var bins = binify(pkg)

  return Promise.all(Object.keys(bins).map(bin => {
    var actualBin = bins[bin]
    var binDir = join(modules, '.bin')
    var externalBinPath = join(binDir, bin)

    return Promise.resolve()
      .then(_ => mkdirp(join(modules, '.bin')))
      .then(_ => {
        var targetPath = normalizePath(join(pkg.name, actualBin))
        if (isWindows) {
          if (!preserveSymlinks) {
            return cmdShim(externalBinPath, '../' + targetPath)
          }
          var proxyFilePath = join(binDir, bin + '.proxy')
          fs.writeFileSync(proxyFilePath, 'require("../' + targetPath + '")', 'utf8')
          return cmdShim(externalBinPath, relative(binDir, proxyFilePath))
        }

        if (!preserveSymlinks) {
          return makeExecutable(join(target, actualBin))
            .then(_ => debug('linking %s -> %s',
              join(target, actualBin),
              externalBinPath))
            .then(_ => relSymlink(
              join(target, actualBin),
              externalBinPath))
        }

        return proxy(externalBinPath, targetPath)
      })
  }))
}

function makeExecutable (filePath) {
  return fs.chmod(filePath, 0o755)
}

function proxy (proxyPath, targetPath) {
  var proxyContent = [
    '#!/bin/sh',
    '":" //# comment; exec /usr/bin/env node --preserve-symlinks "$0" "$@"',
    "require('../" + targetPath + "')"
  ].join('\n')
  fs.writeFileSync(proxyPath, proxyContent, 'utf8')
  return makeExecutable(proxyPath)
}

function cmdShim (proxyPath, targetPath) {
  var nodeOptions = preserveSymlinks ? '--preserve-symlinks' : ''
  var cmdContent = [
    '@IF EXIST "%~dp0\\node.exe" (',
    '  "%~dp0\\node.exe ' + nodeOptions + '"  "%~dp0/' + targetPath + '" %*',
    ') ELSE (',
    '  @SETLOCAL',
    '  @SET PATHEXT=%PATHEXT:;.JS;=;%',
    '  node ' + nodeOptions + '  "%~dp0/' + targetPath + '" %*',
    ')'
  ].join('\n')
  fs.writeFileSync(proxyPath + '.cmd', cmdContent, 'utf8')

  var shContent = [
    '#!/bin/sh',
    'basedir=$(dirname "$(echo "$0" | sed -e \'s,\\,/,g\')")',
    '',
    'case `uname` in',
    '    *CYGWIN*) basedir=`cygpath -w "$basedir"`;;',
    'esac',
    '',
    'if [ -x "$basedir/node" ]; then',
    '  "$basedir/node ' + nodeOptions + '"  "$basedir/' + targetPath + '" "$@"',
    '  ret=$?',
    'else ',
    '  node ' + nodeOptions + '  "$basedir/' + targetPath + '" "$@"',
    '  ret=$?',
    'fi',
    'exit $ret',
    ''
  ].join('\n')
  fs.writeFileSync(proxyPath, shContent, 'utf8')
  return Promise.all([
    makeExecutable(proxyPath + '.cmd'),
    makeExecutable(proxyPath)
  ])
}

/*
 * Like `require()`, but returns `undefined` when it fails
 */

function tryRequire (path) {
  try { return requireJson(path) } catch (e) { }
}
<commit_msg>fix(install): bin files are used once they were created<commit_after>var join = require('path').join
var basename = require('path').basename
var relative = require('path').relative
var semver = require('semver')
var normalizePath = require('normalize-path')
var relSymlink = require('../fs/rel_symlink')
var fs = require('mz/fs')
var mkdirp = require('../fs/mkdirp')
var debug = require('debug')('pnpm:link_bins')
var requireJson = require('../fs/require_json')
var binify = require('../binify')

var preserveSymlinks = semver.satisfies(process.version, '>=6.3.0')
var isWindows = process.platform === 'win32'

module.exports = linkAllBins
module.exports.linkPkgBins = linkPkgBins

function linkAllBins (modules) {
  return Promise.all(
    getDirectories(modules)
      .reduce((pkgDirs, dir) => pkgDirs.concat(isScopedPkgsDir(dir) ? getDirectories(dir) : dir), [])
      .map(pkgDir => linkPkgBins(modules, pkgDir))
  )
}

function getDirectories (srcPath) {
  return fs.readdirSync(srcPath)
    .map(relativePath => join(srcPath, relativePath))
    .filter(absolutePath => fs.statSync(absolutePath).isDirectory())
}

function isScopedPkgsDir (dirPath) {
  return basename(dirPath)[0] === '@'
}

/*
 * Links executable into `node_modules/.bin`.
 *
 * - `modules` (String) - the node_modules path
 * - `target` (String) - where the module is now; read package.json from here
 * - `fullname` (String) - fullname of the module (`rimraf@2.5.1`)
 *
 *     module = 'project/node_modules'
 *     target = 'project/node_modules/.store/rimraf@2.5.1'
 *     linkPkgBins(module, target)
 *
 *     // node_modules/.bin/rimraf -> ../.store/rimraf@2.5.1/cmd.js
 */

function linkPkgBins (modules, target) {
  var pkg = tryRequire(join(target, 'package.json'))

  if (!pkg || !pkg.bin) return

  var bins = binify(pkg)

  return Promise.all(Object.keys(bins).map(bin => {
    var actualBin = bins[bin]
    var binDir = join(modules, '.bin')
    var externalBinPath = join(binDir, bin)

    return Promise.resolve()
      .then(_ => mkdirp(join(modules, '.bin')))
      .then(_ => {
        var targetPath = normalizePath(join(pkg.name, actualBin))
        if (isWindows) {
          if (!preserveSymlinks) {
            return cmdShim(externalBinPath, '../' + targetPath)
          }
          var proxyFilePath = join(binDir, bin + '.proxy')
          fs.writeFileSync(proxyFilePath, 'require("../' + targetPath + '")', 'utf8')
          return cmdShim(externalBinPath, relative(binDir, proxyFilePath))
        }

        if (!preserveSymlinks) {
          return makeExecutable(join(target, actualBin))
            .then(_ => debug('linking %s -> %s',
              join(target, actualBin),
              externalBinPath))
            .then(_ => relSymlink(
              join(target, actualBin),
              externalBinPath))
        }

        return proxy(externalBinPath, targetPath)
      })
  }))
}

function makeExecutable (filePath) {
  return fs.chmod(filePath, 0o755)
}

function proxy (proxyPath, targetPath) {
  var proxyContent = [
    '#!/bin/sh',
    '":" //# comment; exec /usr/bin/env node --preserve-symlinks "$0" "$@"',
    "require('../" + targetPath + "')"
  ].join('\n')
  fs.writeFileSync(proxyPath, proxyContent, 'utf8')
  return makeExecutable(proxyPath)
}

function cmdShim (proxyPath, targetPath) {
  var nodeOptions = preserveSymlinks ? '--preserve-symlinks' : ''
  var cmdContent = [
    '@IF EXIST "%~dp0\\node.exe" (',
    '  "%~dp0\\node.exe ' + nodeOptions + '"  "%~dp0/' + targetPath + '" %*',
    ') ELSE (',
    '  @SETLOCAL',
    '  @SET PATHEXT=%PATHEXT:;.JS;=;%',
    '  node ' + nodeOptions + '  "%~dp0/' + targetPath + '" %*',
    ')'
  ].join('\n')
  fs.writeFileSync(proxyPath + '.cmd', cmdContent, 'utf8')

  var shContent = [
    '#!/bin/sh',
    'basedir=$(dirname "$(echo "$0" | sed -e \'s,\\,/,g\')")',
    '',
    'case `uname` in',
    '    *CYGWIN*) basedir=`cygpath -w "$basedir"`;;',
    'esac',
    '',
    'if [ -x "$basedir/node" ]; then',
    '  "$basedir/node ' + nodeOptions + '"  "$basedir/' + targetPath + '" "$@"',
    '  ret=$?',
    'else ',
    '  node ' + nodeOptions + '  "$basedir/' + targetPath + '" "$@"',
    '  ret=$?',
    'fi',
    'exit $ret',
    ''
  ].join('\n')
  fs.writeFileSync(proxyPath, shContent, 'utf8')
  return Promise.all([
    makeExecutable(proxyPath + '.cmd'),
    makeExecutable(proxyPath)
  ])
}

/*
 * Like `require()`, but returns `undefined` when it fails
 */

function tryRequire (path) {
  try { return requireJson(path) } catch (e) { }
}
<|endoftext|>


<commit_before>/**
 * @author dforrer / https://github.com/dforrer
 */

/**
 * @param object THREE.Object3D
 * @param newGeometry THREE.Geometry
 * @constructor
 */

CmdSetGeometry = function ( object, newGeometry ) {

	Cmd.call( this );

	this.type = 'CmdSetGeometry';
	this.name = 'Set Geometry';
	this.updatable = true;

	this.object = object;
	this.oldGeometry = ( object !== undefined ) ? object.geometry : undefined;
	this.newGeometry = newGeometry;

};

CmdSetGeometry.prototype = {

	execute: function () {

		this.object.geometry.dispose();
		this.object.geometry = this.newGeometry;
		this.object.geometry.computeBoundingSphere();

		this.editor.signals.geometryChanged.dispatch( this.object );
		this.editor.signals.sceneGraphChanged.dispatch();

	},

	undo: function () {

		this.object.geometry.dispose();
		this.object.geometry = this.oldGeometry;
		this.object.geometry.computeBoundingSphere();

		this.editor.signals.geometryChanged.dispatch( this.object );
		this.editor.signals.sceneGraphChanged.dispatch();

	},

	update: function ( cmd ) {

		this.newGeometry = cmd.newGeometry;
		this.newGeometryJSON = cmd.newGeometry.toJSON();

	},

	toJSON: function () {

		var output = Cmd.prototype.toJSON.call( this );

		output.objectUuid = this.object.uuid;
		output.oldGeometry = this.object.geometry.toJSON();
		output.newGeometry = this.newGeometry.toJSON();

		return output;

	},

	fromJSON: function ( json ) {

		Cmd.prototype.fromJSON.call( this, json );

		this.object = this.editor.objectByUuid( json.objectUuid );

		this.oldGeometry = parseGeometry( json.oldGeometry );
		this.newGeometry = parseGeometry( json.newGeometry );

		function parseGeometry ( data ) {

			var loader = new THREE.ObjectLoader();
			return loader.parseGeometries( [ data ] )[ data.uuid ];

		}

	}

};
<commit_msg>Removed unnecessary line<commit_after>/**
 * @author dforrer / https://github.com/dforrer
 */

/**
 * @param object THREE.Object3D
 * @param newGeometry THREE.Geometry
 * @constructor
 */

CmdSetGeometry = function ( object, newGeometry ) {

	Cmd.call( this );

	this.type = 'CmdSetGeometry';
	this.name = 'Set Geometry';
	this.updatable = true;

	this.object = object;
	this.oldGeometry = ( object !== undefined ) ? object.geometry : undefined;
	this.newGeometry = newGeometry;

};

CmdSetGeometry.prototype = {

	execute: function () {

		this.object.geometry.dispose();
		this.object.geometry = this.newGeometry;
		this.object.geometry.computeBoundingSphere();

		this.editor.signals.geometryChanged.dispatch( this.object );
		this.editor.signals.sceneGraphChanged.dispatch();

	},

	undo: function () {

		this.object.geometry.dispose();
		this.object.geometry = this.oldGeometry;
		this.object.geometry.computeBoundingSphere();

		this.editor.signals.geometryChanged.dispatch( this.object );
		this.editor.signals.sceneGraphChanged.dispatch();

	},

	update: function ( cmd ) {

		this.newGeometry = cmd.newGeometry;

	},

	toJSON: function () {

		var output = Cmd.prototype.toJSON.call( this );

		output.objectUuid = this.object.uuid;
		output.oldGeometry = this.object.geometry.toJSON();
		output.newGeometry = this.newGeometry.toJSON();

		return output;

	},

	fromJSON: function ( json ) {

		Cmd.prototype.fromJSON.call( this, json );

		this.object = this.editor.objectByUuid( json.objectUuid );

		this.oldGeometry = parseGeometry( json.oldGeometry );
		this.newGeometry = parseGeometry( json.newGeometry );

		function parseGeometry ( data ) {

			var loader = new THREE.ObjectLoader();
			return loader.parseGeometries( [ data ] )[ data.uuid ];

		}

	}

};
<|endoftext|>


<commit_before>var request = require("./request");
var querystring = require("querystring");
var upload = require("./upload");
var config = require("../../src/config");
var unitTest;

var options = {
    host : config.server.ip,
    port : config.server.port,
    path : '/1/files',
    method : 'POST',
    encoding : 'utf8'
};

exports.testFilesModule = function(test) {
    unitTest = test;
    startTest(test);
};

var startTest = function(test) {
    unitTest = test;
    //upload file
    upload.postImage(options, "../images/coffee.png", {}, function(response) {
        //delete file
        var newFile = JSON.parse(response.body);
        deleteFile(newFile._id, unitTest, function() {
            getFiles(unitTest, function(items) {
                //check item in there
                notfound = true;
                for (var i=0; i < items.length; i++) {
                    notfound = !(items[i]._id == newFile._id);
                    if(!notfound)
                        break;
                };
                unitTest.ok(notfound);
                unitTest.done();
            });
        });
    });
};

var deleteFile = function(id, test, callback) {
    unitTest = test;
    objId = id;
    var postData = querystring.stringify({"url" : "http://domain.com/test.txt", "type": "image" });
    request.post('DELETE', 'files/' + objId, postData, function(res, chunk) {
        unitTest.equal(res.statusCode, 200);
        var response = JSON.parse(chunk);
        callback();
    });
};

var getFiles = function(test, callback) {
    unitTest = test;
    request.get('files/?fields=filename,type&page=1&size=2&orderby=_id&orderdirection=desc', function(res, chunk) {
        unitTest.equal(res.statusCode, 200);
        var response = JSON.parse(chunk);
        callback(response);
    });
};<commit_msg>quick change to make the test running in bash<commit_after>var request = require("./request");
var querystring = require("querystring");
var upload = require("./upload");
var config = require("../../src/config");
var unitTest;

var options = {
    host : config.server.ip,
    port : config.server.port,
    path : '/1/files',
    method : 'POST',
    encoding : 'utf8'
};

exports.testFilesModule = function(test) {
    unitTest = test;
    startTest(test);
};

var startTest = function(test) {
    unitTest = test;
    //upload file
    upload.postImage(options, "images/coffee.png", {}, function(response) {
        //delete file
        var newFile = JSON.parse(response.body);
        deleteFile(newFile._id, unitTest, function() {
            getFiles(unitTest, function(items) {
                //check item in there
                notfound = true;
                for (var i=0; i < items.length; i++) {
                    notfound = !(items[i]._id == newFile._id);
                    if(!notfound)
                        break;
                };
                unitTest.ok(notfound);
                unitTest.done();
            });
        });
    });
};

var deleteFile = function(id, test, callback) {
    unitTest = test;
    objId = id;
    var postData = querystring.stringify({"url" : "http://domain.com/test.txt", "type": "image" });
    request.post('DELETE', 'files/' + objId, postData, function(res, chunk) {
        unitTest.equal(res.statusCode, 200);
        var response = JSON.parse(chunk);
        callback();
    });
};

var getFiles = function(test, callback) {
    unitTest = test;
    request.get('files/?fields=filename,type&page=1&size=2&orderby=_id&orderdirection=desc', function(res, chunk) {
        unitTest.equal(res.statusCode, 200);
        var response = JSON.parse(chunk);
        callback(response);
    });
};<|endoftext|>


<commit_before><commit_msg>rename<commit_after><|endoftext|>


<commit_before>/* eslint-disable max-len */
import React from 'react';
import PropTypes from 'prop-types';

const scale = 1 / 0.375;

const TrafficLight = ({
  onRedClick,
  onYellowClick,
  onGreenClick,
  RedOn,
  YellowOn,
  GreenOn,
  Size,
  BlackColor,
  DisabledColor,
  RedColor,
  YellowColor,
  GreenColor,
  Horizontal,
  ...props
}) => (
  <svg width={`${Size}px`} height={`${Size * scale}px`} viewBox="0 0 60 160" version="1.1" transform={Horizontal ? `rotate(-90 0 ${Size * scale * 0.3125 * -1})` : undefined} {...props}>
    <defs>
      <circle style={{ cursor: onRedClick ? 'pointer' : undefined }} id="redCirclePath" cx="30" cy="30" r="20" />
      <circle style={{ cursor: onYellowClick ? 'pointer' : undefined }} id="yellowCirclePath" cx="30" cy="80" r="20" />
      <circle style={{ cursor: onGreenClick ? 'pointer' : undefined }} id="greenCirclePath" cx="30" cy="130" r="20" />

      <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="shadowFilter">
        <feGaussianBlur stdDeviation="3" in="SourceAlpha" result="shadowBlurInner1" />
        <feOffset dx="0" dy="4" in="shadowBlurInner1" result="shadowOffsetInner1" />
        <feComposite in="shadowOffsetInner1" in2="SourceAlpha" operator="arithmetic" k2="-1" k3="1" result="shadowInnerInner1" />
        <feColorMatrix values="0 0 0 0 0   0 0 0 0 0   0 0 0 0 0  0 0 0 0.5 0" type="matrix" in="shadowInnerInner1" />
      </filter>
    </defs>
    <rect fill={BlackColor} x="0" y="0" width="60" height="160" rx="8" />

    <use fill={RedOn ? RedColor : DisabledColor} fillRule="evenodd" xlinkHref="#redCirclePath" />
    <use fill={YellowOn ? YellowColor : DisabledColor} fillRule="evenodd" xlinkHref="#yellowCirclePath" />
    <use fill={GreenOn ? GreenColor : DisabledColor} fillRule="evenodd" xlinkHref="#greenCirclePath" />

    <g>
      <use onClick={onRedClick} fill="black" fillOpacity="1" filter="url(#shadowFilter)" xlinkHref="#redCirclePath" />
      <use onClick={onYellowClick} fill="black" fillOpacity="1" filter="url(#shadowFilter)" xlinkHref="#yellowCirclePath" />
      <use onClick={onGreenClick} fill="black" fillOpacity="1" filter="url(#shadowFilter)" xlinkHref="#greenCirclePath" />
    </g>
  </svg>
);

TrafficLight.propTypes = {
  onRedClick: PropTypes.func,
  onYellowClick: PropTypes.func,
  onGreenClick: PropTypes.func,
  RedOn: PropTypes.bool,
  YellowOn: PropTypes.bool,
  GreenOn: PropTypes.bool,
  Size: PropTypes.number,
  BlackColor: PropTypes.string,
  DisabledColor: PropTypes.string,
  RedColor: PropTypes.string,
  YellowColor: PropTypes.string,
  GreenColor: PropTypes.string,
  Horizontal: PropTypes.bool,
};

TrafficLight.defaultProps = {
  onRedClick: undefined,
  onYellowClick: undefined,
  onGreenClick: undefined,
  RedOn: false,
  YellowOn: false,
  GreenOn: false,
  Size: 60,
  BlackColor: '#000000',
  DisabledColor: '#4A4A4A',
  RedColor: '#D0021B',
  YellowColor: '#F8E71C',
  GreenColor: '#7ED321',
  Horizontal: false,
};

export default TrafficLight;
<commit_msg>Fix wrong size of svg element<commit_after>/* eslint-disable max-len */
import React from 'react';
import PropTypes from 'prop-types';

const scale = 1 / 0.375;

const TrafficLight = ({
  onRedClick,
  onYellowClick,
  onGreenClick,
  RedOn,
  YellowOn,
  GreenOn,
  Size,
  BlackColor,
  DisabledColor,
  RedColor,
  YellowColor,
  GreenColor,
  Horizontal,
  ...props
}) => (
  <svg width={`${Size * (Horizontal ? scale : 1)}px`} height={`${Size * (Horizontal ? 1 : scale)}px`} viewBox={Horizontal ? "0 0 160 60" : "0 0 60 160"} version="1.1" {...props}>
    <defs>
      <circle style={{ cursor: onRedClick ? 'pointer' : undefined }} id="redCirclePath" cx="30" cy="30" r="20" />
      <circle style={{ cursor: onYellowClick ? 'pointer' : undefined }} id="yellowCirclePath" cx="30" cy="80" r="20" />
      <circle style={{ cursor: onGreenClick ? 'pointer' : undefined }} id="greenCirclePath" cx="30" cy="130" r="20" />

      <filter x="-50%" y="-50%" width="200%" height="200%" filterUnits="objectBoundingBox" id="shadowFilter">
        <feGaussianBlur stdDeviation="3" in="SourceAlpha" result="shadowBlurInner1" />
        <feOffset dx="0" dy="4" in="shadowBlurInner1" result="shadowOffsetInner1" />
        <feComposite in="shadowOffsetInner1" in2="SourceAlpha" operator="arithmetic" k2="-1" k3="1" result="shadowInnerInner1" />
        <feColorMatrix values="0 0 0 0 0   0 0 0 0 0   0 0 0 0 0  0 0 0 0.5 0" type="matrix" in="shadowInnerInner1" />
      </filter>
    </defs>
    <g transform={Horizontal ? `rotate(-90 30 30)` : undefined}>
      <rect fill={BlackColor} x="0" y="0" width="60" height="160" rx="8" />

      <use fill={RedOn ? RedColor : DisabledColor} fillRule="evenodd" xlinkHref="#redCirclePath" />
      <use fill={YellowOn ? YellowColor : DisabledColor} fillRule="evenodd" xlinkHref="#yellowCirclePath" />
      <use fill={GreenOn ? GreenColor : DisabledColor} fillRule="evenodd" xlinkHref="#greenCirclePath" />

      <use onClick={onRedClick} fill="black" fillOpacity="1" filter="url(#shadowFilter)" xlinkHref="#redCirclePath" />
      <use onClick={onYellowClick} fill="black" fillOpacity="1" filter="url(#shadowFilter)" xlinkHref="#yellowCirclePath" />
      <use onClick={onGreenClick} fill="black" fillOpacity="1" filter="url(#shadowFilter)" xlinkHref="#greenCirclePath" />
    </g>
  </svg>
);

TrafficLight.propTypes = {
  onRedClick: PropTypes.func,
  onYellowClick: PropTypes.func,
  onGreenClick: PropTypes.func,
  RedOn: PropTypes.bool,
  YellowOn: PropTypes.bool,
  GreenOn: PropTypes.bool,
  Size: PropTypes.number,
  BlackColor: PropTypes.string,
  DisabledColor: PropTypes.string,
  RedColor: PropTypes.string,
  YellowColor: PropTypes.string,
  GreenColor: PropTypes.string,
  Horizontal: PropTypes.bool,
};

TrafficLight.defaultProps = {
  onRedClick: undefined,
  onYellowClick: undefined,
  onGreenClick: undefined,
  RedOn: false,
  YellowOn: false,
  GreenOn: false,
  Size: 60,
  BlackColor: '#000000',
  DisabledColor: '#4A4A4A',
  RedColor: '#D0021B',
  YellowColor: '#F8E71C',
  GreenColor: '#7ED321',
  Horizontal: false,
};

export default TrafficLight;
<|endoftext|>


<commit_before>import PNotify from './PNotifyCore.html';

// Factory functions.
export const alert = options => new PNotify(getDefaultArgs(options));
export const notice = options => new PNotify(getDefaultArgs(options, 'notice'));
export const info = options => new PNotify(getDefaultArgs(options, 'info'));
export const success = options => new PNotify(getDefaultArgs(options, 'success'));
export const error = options => new PNotify(getDefaultArgs(options, 'error'));

// Default arguments for the new notice helper functions.
function getDefaultArgs (options, type) {
  if (typeof options !== 'object') {
    options = { text: options };
  }

  // Only assign the type if it was requested, so we don't overwrite
  // options.type if it has something assigned.
  if (type) {
    options.type = type;
  }

  // Experiment that doesn't work:
  let target = document.body;

  if ('stack' in options && options.stack && options.stack.context) {
    target = options.stack.context;
  }

  return { target, props: options };
}

export default PNotify;
export * from './PNotifyCore.html';
export { default as Stack } from './Stack.js';
<commit_msg>Remove old comment.<commit_after>import PNotify from './PNotifyCore.html';

// Factory functions.
export const alert = options => new PNotify(getDefaultArgs(options));
export const notice = options => new PNotify(getDefaultArgs(options, 'notice'));
export const info = options => new PNotify(getDefaultArgs(options, 'info'));
export const success = options => new PNotify(getDefaultArgs(options, 'success'));
export const error = options => new PNotify(getDefaultArgs(options, 'error'));

// Default arguments for the new notice helper functions.
function getDefaultArgs (options, type) {
  if (typeof options !== 'object') {
    options = { text: options };
  }

  // Only assign the type if it was requested, so we don't overwrite
  // options.type if it has something assigned.
  if (type) {
    options.type = type;
  }

  let target = document.body;

  if ('stack' in options && options.stack && options.stack.context) {
    target = options.stack.context;
  }

  return { target, props: options };
}

export default PNotify;
export * from './PNotifyCore.html';
export { default as Stack } from './Stack.js';
<|endoftext|>


<commit_before>
import _ from 'underscore';
import Victor from 'Victor';

const State = {
  MOVING: 'MOVING',
  GROWING: 'GROWING',
  THINKING: 'THINKING'
};

export const create = (leg1, leg2, leg3) => {
  return {
    leg1, leg2, leg3,
    state: State.THINKING
  };
};

export const legs = ({leg1, leg2, leg3}) => {
  return {
    leg1, leg2, leg3
  };
};

export const centre = ({leg1, leg2, leg3}) => {
  return Victor(
    (leg1.x + leg2.x + leg3.x) / 3,
    (leg1.y + leg2.y + leg3.y) / 3
  );
};

export const area = ({leg1, leg2, leg3}) => {
  return Math.abs(
    (leg1.x * (leg2.y - leg3.y)) +
    (leg2.x * (leg3.y - leg1.y)) +
    (leg3.x * (leg1.y - leg2.y))
  ) / 2;
};

export const movePoint = (tripod, target) => {
  return _.chain(legs(tripod)).map(
    (p, name) => {
      return {name, distance: p.distance(target)};
    }
  ).max(
    ({distance}) => distance
  ).value().name;
};

export const newPoint = (tripod, target) => {
  const movePointName = movePoint(tripod, target);

  const pC = centre(tripod);

  const movePoint = tripod[movePointName];
  const moveDistance = movePoint.distance(pC) * 4;

  const newPoint = pC.subtract(movePoint).normalize().multiply(moveDistance).add(movePoint);

  return newPoint;
};
<commit_msg>Flesh out tripod functionality<commit_after>
import _ from 'underscore';
import Victor from 'Victor';

const State = {
  MOVING: 'MOVING',
  GROWING: 'GROWING',
  THINKING: 'THINKING'
};
const ERROR = 'ERROR';

export const create = (leg1, leg2, leg3) => {
  return {
    leg1, leg2, leg3,
    state: State.THINKING,
    stateData: {}
  };
};

export const legs = ({leg1, leg2, leg3}) => {
  return {
    leg1, leg2, leg3
  };
};

export const centre = ({leg1, leg2, leg3}) => {
  return Victor(
    (leg1.x + leg2.x + leg3.x) / 3,
    (leg1.y + leg2.y + leg3.y) / 3
  );
};

export const area = ({leg1, leg2, leg3}) => {
  return Math.abs(
    (leg1.x * (leg2.y - leg3.y)) +
    (leg2.x * (leg3.y - leg1.y)) +
    (leg3.x * (leg1.y - leg2.y))
  ) / 2;
};

/**
   Moving state functions
 */
export const movingLeg = (tripod, target) => {
  return _.chain(legs(tripod)).map(
    (p, name) => {
      return {name, distance: p.distance(target)};
    }
  ).max(
    ({distance}) => distance
  ).value().name;
};

export const startMoving = (tripod, target) => {
  const movingLegName = movingLeg(tripod, target);
  const movingLeg = tripod[movingLegName];
  const tC = centre(tripod);

  const direction = tC.clone().subtract(movingLeg).normalize();
  const moveDistance = movingLeg.distance(tC) * 4;
  const legTarget = direction.clone().multiply(moveDistance).add(movingLeg);

  tripod.state = State.MOVING;
  tripod.stateData = {
    movingLeg: movingLegName,
    target: legTarget,
    stepsTaken: 0,
    stepsInMovement: 10
  };
};

export const move = (tripod) => {
  if (tripod.state !== State.MOVING) {
    console.log(`Shouldn't be moving in ${tripod.state} state`);
    return ERROR;
  }

  tripod.stateData.stepsTaken += 1;
  if (tripod.stateData.stepsTaken >= tripod.stateData.stepsInMovement) {
    movingLeg.copy(target);
    return State.THINKING;
  }
  // Steps still to take
  const movingLeg = tripod[tripod.stateData.movingLeg];
  const target = tripod.stateData.target;
  const distance = target.distance(movingLeg);
  const step = (distance / tripod.stateData.stepsInMovement);
  const dirVector = target.clone().subtract(movingLeg).normalize().multiply(step);
  movingLeg.add(dirVector);
  return State.MOVING;
};

/**
   Thinking state functions
 */

export const startThinking = (tripod) => {
  tripod.state = State.THINKING;
  tripod.stateData = {};
};

export const think = (tripod) => {
  return tripod.state;
};

/**
   Growing state functions
 */

export const startGrowing = (tripod) => {
  tripod.state = State.GROWING;
  tripod.stateData = {};
};

export const grow = () => {
  return State.THINKING;
};

/**
   State Machine functions
 */
export const live = (tripod) => {
  switch (tripod.state) {
  case State.MOVING:
    handleState(move(tripod));
    break;
  case State.GROWING:
    handleState(grow(tripod));
    break;
  case State.THINKING:
    handleState(think(tripod));
    break;
  default:
    handleState(think(tripod));
    break;
  }
};

export const handleState = (tripod, newState) => {
  if (newState === tripod.state) {
    // no state change
    return;
  }
  switch (tripod.state) {
  case State.MOVING:
    startMoving(tripod);
    break;
  case State.GROWING:
    startGrowing(tripod);
    break;
  case State.THINKING:
    startThinking(tripod);
    break;
  default:
    if (newState === ERROR) {
      // Handle error
    }
    startThinking(tripod);
    break;
  }
};
<|endoftext|>


<commit_before>(function (angular) {
    'use strict';

    var module = angular.module('externalLinkInterceptor', [
        'ngRoute',
        'ui.bootstrap'
    ]);

    module.config([
        '$routeProvider',
        function ($routeProvider) {
            $routeProvider
                .when('/external-link/', {
                    templateUrl: 'templates/external_link/page.html',
                    controller: 'ExternalLinkCtrl'
                });
        }
    ]);

    module.run([
        '$templateCache',
        function ($templateCache) {
            $templateCache.put('templates/external_link/message.html',
                '
You are now leaving this website.
' +
                '
' +
                    'Continue' +
                    'Cancel' +
                '
'
            );

            $templateCache.put('templates/external_link/page.html',
                '

'
            );
        }
    ]);

    module.controller('ExternalLinkCtrl', [
        '$scope', '$location',
        function ($scope, $location) {
            $scope.externalUrl = $location.$$search.next;

            $scope.cancel = function () {
                if ($location.$$search.prev) {
                    $location.url($location.$$search.prev);
                } else {
                    $location.url('/');
                }
            };
        }
    ]);

    module.service('ExternalLinkService', [
        '$filter', '$location', '$modal',
        function ($filter, $location, $modal) {

            var ExternalLinkService = {
                externalLinkRE: new RegExp(/^([^:\/?#]+:)?(?:\/\/([^\/?#]*))?([^?#]+)?(\?[^#]*)?(#.*)?/),
                // External url testing function from http://stackoverflow.com/a/6238456
                isExternal: function (url) {
                    var match = url.match(ExternalLinkService.externalLinkRE);

                    if (typeof match[1] === 'string' && match[1].length > 0) {
                        if (match[1] === 'mailto:' || match[1] === 'tel:') {
                            return false;
                        }

                        if (match[1].toLowerCase() !== location.protocol) {
                            return true;
                        }
                    }

                    if (typeof match[2] === 'string' && match[2].length > 0 && match[2].replace(new RegExp(':(' + {
                        'http:': 80,
                        'https:': 443
                    }[location.protocol] + ')?$'), '') !== location.host) { return true; }
                    return false;
                },
                externalModal: function (e, href) {
                    e.preventDefault();

                    // Open a bootstrap-ui modal.
                    $modal.open({
                        templateUrl: 'templates/external_link/message.html',
                        resolve: {
                            externalUrl: function () {
                                return href;
                            }
                        },
                        controller: [
                            '$scope', '$modalInstance', 'externalUrl',
                            function ($scope, $modalInstance, externalUrl) {
                                $scope.externalUrl = externalUrl;

                                $scope.cancel = function () {
                                    $modalInstance.dismiss('cancel');
                                };

                                // Pass through target attribute, so links that
                                // should open in a new window can.
                                var element = angular.element(e.currentTarget);
                                $scope.target = element.attr('target');
                            }
                        ]
                    });
                },
                bindModal: function (element, newValue) {
                    // The click event may have been bound based on a
                    // previous href value.
                    var clickFunction = function (e) {
                        ExternalLinkService.externalModal(e, newValue);
                    };
                    element.off('click', clickFunction);
                    if (newValue) {
                        // If the link is external.
                        if (ExternalLinkService.isExternal(newValue)) {
                            // Rewrite the url to go to the external link route.
                            // Adds a `next` parameter containing the external link and
                            // a `prev` parameter containing the current path, so that
                            // we can navigate back to where the user came from.
                            element.attr('href', $filter('reverseUrl')('ExternalLinkCtrl') + '?next=' + encodeURI(newValue) + '&prev=' + encodeURI($location.path()));

                            element.on('click', clickFunction);
                        }
                    }
                }
            };

            return ExternalLinkService;
        }
    ]);

    module.directive('a', [
        'ExternalLinkService',
        function (ExternalLinkService) {
            return {
                restrict: 'E',
                link: function (scope, element, attrs) {
                    // If the link does not have an attribute to allow it to by-pass the warning.
                    if (!attrs.allowExternal) {
                        attrs.$observe('href', function (newValue) {
                            ExternalLinkService.bindModal(element, newValue);
                        });
                    }
                }
            };
        }
    ]);

}(window.angular));
<commit_msg>Not load the whole ui.bootstrap module<commit_after>(function (angular) {
    'use strict';

    var module = angular.module('externalLinkInterceptor', [
        'ngRoute',
        'ui.bootstrap.modal'
    ]);

    module.config([
        '$routeProvider',
        function ($routeProvider) {
            $routeProvider
                .when('/external-link/', {
                    templateUrl: 'templates/external_link/page.html',
                    controller: 'ExternalLinkCtrl'
                });
        }
    ]);

    module.run([
        '$templateCache',
        function ($templateCache) {
            $templateCache.put('templates/external_link/message.html',
                '
You are now leaving this website.
' +
                '
' +
                    'Continue' +
                    'Cancel' +
                '
'
            );

            $templateCache.put('templates/external_link/page.html',
                '

'
            );
        }
    ]);

    module.controller('ExternalLinkCtrl', [
        '$scope', '$location',
        function ($scope, $location) {
            $scope.externalUrl = $location.$$search.next;

            $scope.cancel = function () {
                if ($location.$$search.prev) {
                    $location.url($location.$$search.prev);
                } else {
                    $location.url('/');
                }
            };
        }
    ]);

    module.service('ExternalLinkService', [
        '$filter', '$location', '$modal',
        function ($filter, $location, $modal) {

            var ExternalLinkService = {
                externalLinkRE: new RegExp(/^([^:\/?#]+:)?(?:\/\/([^\/?#]*))?([^?#]+)?(\?[^#]*)?(#.*)?/),
                // External url testing function from http://stackoverflow.com/a/6238456
                isExternal: function (url) {
                    var match = url.match(ExternalLinkService.externalLinkRE);

                    if (typeof match[1] === 'string' && match[1].length > 0) {
                        if (match[1] === 'mailto:' || match[1] === 'tel:') {
                            return false;
                        }

                        if (match[1].toLowerCase() !== location.protocol) {
                            return true;
                        }
                    }

                    if (typeof match[2] === 'string' && match[2].length > 0 && match[2].replace(new RegExp(':(' + {
                        'http:': 80,
                        'https:': 443
                    }[location.protocol] + ')?$'), '') !== location.host) { return true; }
                    return false;
                },
                externalModal: function (e, href) {
                    e.preventDefault();

                    // Open a bootstrap-ui modal.
                    $modal.open({
                        templateUrl: 'templates/external_link/message.html',
                        resolve: {
                            externalUrl: function () {
                                return href;
                            }
                        },
                        controller: [
                            '$scope', '$modalInstance', 'externalUrl',
                            function ($scope, $modalInstance, externalUrl) {
                                $scope.externalUrl = externalUrl;

                                $scope.cancel = function () {
                                    $modalInstance.dismiss('cancel');
                                };

                                // Pass through target attribute, so links that
                                // should open in a new window can.
                                var element = angular.element(e.currentTarget);
                                $scope.target = element.attr('target');
                            }
                        ]
                    });
                },
                bindModal: function (element, newValue) {
                    // The click event may have been bound based on a
                    // previous href value.
                    var clickFunction = function (e) {
                        ExternalLinkService.externalModal(e, newValue);
                    };
                    element.off('click', clickFunction);
                    if (newValue) {
                        // If the link is external.
                        if (ExternalLinkService.isExternal(newValue)) {
                            // Rewrite the url to go to the external link route.
                            // Adds a `next` parameter containing the external link and
                            // a `prev` parameter containing the current path, so that
                            // we can navigate back to where the user came from.
                            element.attr('href', $filter('reverseUrl')('ExternalLinkCtrl') + '?next=' + encodeURI(newValue) + '&prev=' + encodeURI($location.path()));

                            element.on('click', clickFunction);
                        }
                    }
                }
            };

            return ExternalLinkService;
        }
    ]);

    module.directive('a', [
        'ExternalLinkService',
        function (ExternalLinkService) {
            return {
                restrict: 'E',
                link: function (scope, element, attrs) {
                    // If the link does not have an attribute to allow it to by-pass the warning.
                    if (!attrs.allowExternal) {
                        attrs.$observe('href', function (newValue) {
                            ExternalLinkService.bindModal(element, newValue);
                        });
                    }
                }
            };
        }
    ]);

}(window.angular));
<|endoftext|>


<commit_before><commit_msg>Implement report-password component + tests<commit_after><|endoftext|>


<commit_before>import React, { Component } from 'react';
import { map, mapValues, reduce } from 'lodash';
import { fieldLocator } from '../../helpers/index';
import { highlightNodes } from '../../modules/graph/index';
import { Icon } from '../../components/index';
import DOMPurify from 'dompurify';

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

        this.state = {
            editNode: null,
            expanded: false
        };
    }

    handleTableAddColumn(field) {
        const { onTableAddColumn } = this.props;
        onTableAddColumn(field);
    }

    handleTableRemoveColumn(field) {
        const { onTableRemoveColumn } = this.props;
        onTableRemoveColumn(field);
    }

    handleMouseOver(id) {
        /*
        const { onMouseOver } = this.props;
        onMouseOver({nodes: [id]});
        */
    }

    extractAllFields(fields, keySeed = false) {
        return reduce(mapValues(fields, (value, key) => {
            const keyParts = [key];
            if (keySeed) {
                keyParts.unshift(keySeed);
            }

            const useKey = keyParts.join('.');
            if (value === null ) {
               return [];
            } else if (typeof value.map == 'function') {
                return [useKey];
            } else if (typeof value == 'object') {
                return [].concat(this.extractAllFields(value, useKey));
            } else {
                return [useKey];
            }
        }), (result, value) => {
            return result.concat(value);
        });
    }

    renderDetails(columns) {
        const { record } = this.props;

        const allFields = this.extractAllFields(record.fields, false);

        const expandedFields = map(allFields, (value, key) => {
            const highlight =  (record.highlight || {});
            const field_value = highlight[value] || fieldLocator(record.fields, value) ;

            const clean = DOMPurify.sanitize(field_value, { ALLOWED_TAGS: ['p', 'br', 'em']});
            return (

                    {value}
                        <Icon onClick={() => this.handleTableAddColumn(value)}
                            name="ion-ios-plus"
                            style={{marginLeft: '8px', lineHeight: '20px', fontSize: '12px'}}/>

            );
        });

        return (

{ expandedFields }

        );
    }

    render() {
        const { record, columns, node, expanded, className } = this.props;
        if (!expanded) {
            return null;
        }

        return (

                { this.renderDetails(columns) }

        );
    }
}
<commit_msg>fix html rendering of table<commit_after>import React, { Component } from 'react';
import { map, mapValues, reduce } from 'lodash';
import { fieldLocator } from '../../helpers/index';
import { highlightNodes } from '../../modules/graph/index';
import { Icon } from '../../components/index';
import DOMPurify from 'dompurify';

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

        this.state = {
            editNode: null,
            expanded: false
        };
    }

    handleTableAddColumn(field) {
        const { onTableAddColumn } = this.props;
        onTableAddColumn(field);
    }

    handleTableRemoveColumn(field) {
        const { onTableRemoveColumn } = this.props;
        onTableRemoveColumn(field);
    }

    handleMouseOver(id) {
        /*
        const { onMouseOver } = this.props;
        onMouseOver({nodes: [id]});
        */
    }

    extractAllFields(fields, keySeed = false) {
        return reduce(mapValues(fields, (value, key) => {
            const keyParts = [key];
            if (keySeed) {
                keyParts.unshift(keySeed);
            }

            const useKey = keyParts.join('.');
            if (value === null ) {
               return [];
            } else if (typeof value.map == 'function') {
                return [useKey];
            } else if (typeof value == 'object') {
                return [].concat(this.extractAllFields(value, useKey));
            } else {
                return [useKey];
            }
        }), (result, value) => {
            return result.concat(value);
        });
    }

    renderDetails(columns) {
        const { record } = this.props;

        const allFields = this.extractAllFields(record.fields, false);

        const expandedFields = map(allFields, (value, key) => {
            const highlight =  (record.highlight || {});
            const field_value = highlight[value] || fieldLocator(record.fields, value) ;
            return (

                    {value}
                        <Icon onClick={() => this.handleTableAddColumn(value)}
                            name="ion-ios-plus"
                            style={{marginLeft: '8px', lineHeight: '20px', fontSize: '12px'}}/>

                    {field_value}

            );
        });

        return (

{ expandedFields }

        );
    }

    render() {
        const { record, columns, node, expanded, className } = this.props;
        if (!expanded) {
            return null;
        }

        return (

                { this.renderDetails(columns) }

        );
    }
}
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Relay from 'react-relay/classic';
import { FormattedMessage } from 'react-intl';
import styled from 'styled-components';
import CreateRelatedMedia from './CreateRelatedMedia';
import MediaRoute from '../../relay/MediaRoute';
import mediaFragment from '../../relay/mediaFragment';
import MediaDetail from './MediaDetail';
import MediasLoading from './MediasLoading';
import CheckContext from '../../CheckContext';
import { getFilters } from '../../helpers';
import {
  FlexRow,
  black54,
  black87,
  body1,
  subheading2,
  units,
} from '../../styles/js/shared';

const StyledHeaderRow = styled.div`
  justify-content: space-between;
  display: flex;
  color: ${black54};
  font: ${body1};
  height: ${units(6)};

  h2 {
    color: ${black87};
    flex: 1;
    font: ${subheading2};
    margin: 0;
  }
`;

const previousFilters = {};

class MediaRelatedComponent extends Component {
  constructor(props) {
    super(props);

    this.state = {};
  }

  componentDidMount() {
    this.subscribe();
  }

  componentWillUpdate(nextProps) {
    if (this.props.media.dbid !== nextProps.media.dbid) {
      this.unsubscribe();
    }
  }

  componentDidUpdate(prevProps) {
    if (this.props.media.dbid !== prevProps.media.dbid) {
      this.subscribe();
    }
  }

  componentWillUnmount() {
    this.unsubscribe();
  }

  getContext() {
    return new CheckContext(this).getContextStore();
  }

  subscribe() {
    const { pusher } = this.getContext();
    if (pusher) {
      pusher.subscribe(this.props.media.pusher_channel).bind('relationship_change', 'MediaRelated', (data, run) => {
        const relationship = JSON.parse(data.message);
        if (
          (this.getContext().clientSessionId !== data.actor_session_id) &&
          (relationship.source_id === this.props.media.dbid)
        ) {
          if (run) {
            this.props.relay.forceFetch();
            return true;
          }
          return {
            id: `media-relationships-${this.props.media.dbid}`,
            callback: this.props.relay.forceFetch,
          };
        }
        return false;
      });
    }
  }

  unsubscribe() {
    const { pusher } = this.getContext();
    if (pusher) {
      pusher.unsubscribe(this.props.media.pusher_channel);
    }
  }

  render() {
    const filters = getFilters();
    const { dbid } = this.props.media;

    const medias = [];
    const { relationships } = this.props.media;
    const { targets_count, sources_count } = relationships;
    const targets = relationships.targets.edges;
    const sources = relationships.sources.edges;
    let filtered_count = 0;
    const total = targets_count + sources_count;

    if (dbid in previousFilters && filters !== previousFilters[dbid]) {
      previousFilters[dbid] = filters;
      this.props.relay.setVariables({ filters });
      this.props.relay.forceFetch();
    } else if (targets.length > 0) {
      targets[0].node.targets.edges.forEach((child) => {
        medias.push({ node: Object.assign(child.node, { target_id: targets[0].node.id }) });
      });
      filtered_count = total - medias.length;
    } else if (sources.length > 0) {
      medias.push({ node: sources[0].node.source });
      sources[0].node.siblings.edges.forEach((sibling) => {
        if (sibling.node.id !== this.props.media.id) {
          medias.push({ node: Object.assign(sibling.node, { source_id: sources[0].node.id }) });
        }
      });
    }

    return (

        { this.props.showHeader ?
           : null }

        { (this.props.showNumbers && medias.length > 0) ?
           : null }

        <FlexRow>
          { (sources_count === 0 && targets_count === 0) ?
            null :

              {medias.map((item) => {
                if (item.node.archived) {
                  return null;
                }
                return (

                    {<MediaDetail
                      media={item.node}
                      condensed
                      currentRelatedMedia={this.props.media}
                      parentComponent={this}
                      parentComponentName="MediaRelated"
                      smoochBotInstalled={this.props.smoochBotInstalled}
                      hideRelated
                    />}
                    {
}

                );
              })}

          }
        </FlexRow>

    );
  }
}

MediaRelatedComponent.contextTypes = {
  store: PropTypes.object,
};

const MediaRelatedContainer = Relay.createContainer(MediaRelatedComponent, {
  initialVariables: {
    contextId: null,
    filters: getFilters(),
  },
  fragments: {
    media: () => Relay.QL`
      fragment on ProjectMedia {
        id
        dbid
        archived
        permissions
        pusher_channel
        media {
          quote
        }
        project {
          dbid
          search_id
          permissions
          team {
            search_id
            verification_statuses
            translation_statuses
          }
        }
        relationships {
          id
          target_id
          source_id
          targets_count
          sources_count
          targets(first: 10000, filters: $filters) {
            edges {
              node {
                id
                type
                targets(first: 10000) {
                  edges {
                    node {
                      __typename
                      ${mediaFragment}
                    }
                  }
                }
              }
            }
          }
          sources(first: 10000) {
            edges {
              node {
                id
                type
                siblings(first: 10000) {
                  edges {
                    node {
                      ${mediaFragment}
                    }
                  }
                }
                source {
                  ${mediaFragment}
                }
              }
            }
          }
        }
      }
    `,
  },
});

const MediaRelated = (props) => {
  const ids = `${props.media.dbid},${props.media.project_id}`;
  const route = new MediaRoute({ ids });

  return (
    <Relay.RootContainer
      Component={MediaRelatedContainer}
      renderFetched={data => <MediaRelatedContainer {...props} {...data} />}
      route={route}
      renderLoading={() => <MediasLoading count={1} />}
    />
  );
};

export default MediaRelated;
<commit_msg>Fix first-time item expansion for children, for real #7505<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Relay from 'react-relay/classic';
import { FormattedMessage } from 'react-intl';
import styled from 'styled-components';
import CreateRelatedMedia from './CreateRelatedMedia';
import MediaRoute from '../../relay/MediaRoute';
import mediaFragment from '../../relay/mediaFragment';
import MediaDetail from './MediaDetail';
import MediasLoading from './MediasLoading';
import CheckContext from '../../CheckContext';
import { getFilters } from '../../helpers';
import {
  FlexRow,
  black54,
  black87,
  body1,
  subheading2,
  units,
} from '../../styles/js/shared';

const StyledHeaderRow = styled.div`
  justify-content: space-between;
  display: flex;
  color: ${black54};
  font: ${body1};
  height: ${units(6)};

  h2 {
    color: ${black87};
    flex: 1;
    font: ${subheading2};
    margin: 0;
  }
`;

const previousFilters = {};

class MediaRelatedComponent extends Component {
  constructor(props) {
    super(props);

    this.state = {};
  }

  componentDidMount() {
    this.subscribe();
  }

  componentWillUpdate(nextProps) {
    if (this.props.media.dbid !== nextProps.media.dbid) {
      this.unsubscribe();
    }
  }

  componentDidUpdate(prevProps) {
    if (this.props.media.dbid !== prevProps.media.dbid) {
      this.subscribe();
    }
  }

  componentWillUnmount() {
    this.unsubscribe();
  }

  getContext() {
    return new CheckContext(this).getContextStore();
  }

  subscribe() {
    const { pusher } = this.getContext();
    if (pusher) {
      pusher.subscribe(this.props.media.pusher_channel).bind('relationship_change', 'MediaRelated', (data, run) => {
        const relationship = JSON.parse(data.message);
        if (
          (this.getContext().clientSessionId !== data.actor_session_id) &&
          (relationship.source_id === this.props.media.dbid)
        ) {
          if (run) {
            this.props.relay.forceFetch();
            return true;
          }
          return {
            id: `media-relationships-${this.props.media.dbid}`,
            callback: this.props.relay.forceFetch,
          };
        }
        return false;
      });
    }
  }

  unsubscribe() {
    const { pusher } = this.getContext();
    if (pusher) {
      pusher.unsubscribe(this.props.media.pusher_channel);
    }
  }

  render() {
    const filters = getFilters();
    const { dbid } = this.props.media;

    const medias = [];
    const { relationships } = this.props.media;
    const { targets_count, sources_count } = relationships;
    const targets = relationships.targets.edges;
    const sources = relationships.sources.edges;
    let filtered_count = 0;
    const total = targets_count + sources_count;

    if (dbid in previousFilters && filters !== previousFilters[dbid]) {
      this.props.relay.setVariables({ filters });
      this.props.relay.forceFetch();
    } else if (targets.length > 0) {
      targets[0].node.targets.edges.forEach((child) => {
        medias.push({ node: Object.assign(child.node, { target_id: targets[0].node.id }) });
      });
      filtered_count = total - medias.length;
    } else if (sources.length > 0) {
      medias.push({ node: sources[0].node.source });
      sources[0].node.siblings.edges.forEach((sibling) => {
        if (sibling.node.id !== this.props.media.id) {
          medias.push({ node: Object.assign(sibling.node, { source_id: sources[0].node.id }) });
        }
      });
    }
    previousFilters[dbid] = filters;

    return (

        { this.props.showHeader ?
           : null }

        { (this.props.showNumbers && medias.length > 0) ?
           : null }

        <FlexRow>
          { (sources_count === 0 && targets_count === 0) ?
            null :

              {medias.map((item) => {
                if (item.node.archived) {
                  return null;
                }
                return (

                    {<MediaDetail
                      media={item.node}
                      condensed
                      currentRelatedMedia={this.props.media}
                      parentComponent={this}
                      parentComponentName="MediaRelated"
                      smoochBotInstalled={this.props.smoochBotInstalled}
                      hideRelated
                    />}
                    {
}

                );
              })}

          }
        </FlexRow>

    );
  }
}

MediaRelatedComponent.contextTypes = {
  store: PropTypes.object,
};

const MediaRelatedContainer = Relay.createContainer(MediaRelatedComponent, {
  initialVariables: {
    contextId: null,
    filters: getFilters(),
  },
  fragments: {
    media: () => Relay.QL`
      fragment on ProjectMedia {
        id
        dbid
        archived
        permissions
        pusher_channel
        media {
          quote
        }
        project {
          dbid
          search_id
          permissions
          team {
            search_id
            verification_statuses
            translation_statuses
          }
        }
        relationships {
          id
          target_id
          source_id
          targets_count
          sources_count
          targets(first: 10000, filters: $filters) {
            edges {
              node {
                id
                type
                targets(first: 10000) {
                  edges {
                    node {
                      __typename
                      ${mediaFragment}
                    }
                  }
                }
              }
            }
          }
          sources(first: 10000) {
            edges {
              node {
                id
                type
                siblings(first: 10000) {
                  edges {
                    node {
                      ${mediaFragment}
                    }
                  }
                }
                source {
                  ${mediaFragment}
                }
              }
            }
          }
        }
      }
    `,
  },
});

const MediaRelated = (props) => {
  const ids = `${props.media.dbid},${props.media.project_id}`;
  const route = new MediaRoute({ ids });

  return (
    <Relay.RootContainer
      Component={MediaRelatedContainer}
      renderFetched={data => <MediaRelatedContainer {...props} {...data} />}
      route={route}
      renderLoading={() => <MediasLoading count={1} />}
    />
  );
};

export default MediaRelated;
<|endoftext|>


<commit_before>import declare from 'dojo/_base/declare';
import lang from 'dojo/_base/lang';
import View from 'argos/View';
import getResource from 'argos/I18n';

const resource = getResource('logOff');

const __class = declare('crm.Views.LogOff', [View], {
  // Templates
  widgetTemplate: new Simplate([
    '
',
    '
{%= $.messageText %}
',
    '{%: $.loginText %}',
    '
',
  ]),

  // Localization
  messageText: resource.messageText,
  loginText: resource.loginText,
  titleText: resource.titleText,

  id: 'logoff',

  login: function login() {
    window.open('#_login', '_blank', 'menubar,status,scrollbars,toolbar,location,personalbar');
  },

  createToolLayout: function createToolLayout() {
    return this.tools || (this.tools = {
      bbar: false,
      tbar: false,
    });
  },
});

lang.setObject('Mobile.SalesLogix.Views.LogOff', __class);
export default __class;
<commit_msg>INFORCRM-12293: Replaced the window.open... with window.location.reload() to force the refresh of the back to show the login again.<commit_after>import declare from 'dojo/_base/declare';
import lang from 'dojo/_base/lang';
import View from 'argos/View';
import getResource from 'argos/I18n';

const resource = getResource('logOff');

const __class = declare('crm.Views.LogOff', [View], {
  // Templates
  widgetTemplate: new Simplate([
    '
',
    '
{%= $.messageText %}
',
    '{%: $.loginText %}',
    '
',
  ]),

  // Localization
  messageText: resource.messageText,
  loginText: resource.loginText,
  titleText: resource.titleText,

  id: 'logoff',

  login: function login() {
    window.location.reload();
  },

  createToolLayout: function createToolLayout() {
    return this.tools || (this.tools = {
      bbar: false,
      tbar: false,
    });
  },
});

lang.setObject('Mobile.SalesLogix.Views.LogOff', __class);
export default __class;
<|endoftext|>


<commit_before>var spawn = require('child_process').spawn;
var log = require('../logger').create('launcher');
var fs = require('fs');

var BaseBrowser = require('./Base');

var PREFS =
    'user_pref("browser.shell.checkDefaultBrowser", false);\n' +
    'user_pref("browser.bookmarks.restore_default_bookmarks", false);\n';

// https://developer.mozilla.org/en-US/docs/Command_Line_Options
var FirefoxBrowser = function(id) {
  BaseBrowser.apply(this, arguments);

  this._start = function(url) {
    var self = this;
    var command = this._getCommand();
    var errorOutput = '';

    var p = spawn(command, ['-CreateProfile', 'testacular-' + id + ' ' + self._tempDir, '--new-instance']);

    p.stderr.on('data', function(data) {
      errorOutput += data.toString();
    });

    p.on('close', function() {
      var match = /at\s\'(.*)[\/\\]prefs\.js\'/.exec(errorOutput);

      if (match) {
        var profile = self._tempDir = match[1];

        fs.createWriteStream(profile + '/prefs.js', {flags: 'a'}).write(PREFS);
        self._execCommand(command, ['-profile', profile, url]);
      } else {
        log.warn('Cannot create Firefox profile, reusing current.');
        self._execCommand(command, [url]);
      }
    });
  };
};

FirefoxBrowser.prototype = {
  name: 'Firefox',

  DEFAULT_CMD: {
    linux: 'firefox',
    darwin: '/Applications/Firefox.app/Contents/MacOS/firefox-bin',
    win32: process.env.ProgramFiles + '\\Mozilla Firefox\\firefox.exe'
  },
  ENV_CMD: 'FIREFOX_BIN'
};

// PUBLISH
module.exports = FirefoxBrowser;
<commit_msg>Firefox launcher use -no-remote<commit_after>var spawn = require('child_process').spawn;
var log = require('../logger').create('launcher');
var fs = require('fs');

var BaseBrowser = require('./Base');

var PREFS =
    'user_pref("browser.shell.checkDefaultBrowser", false);\n' +
    'user_pref("browser.bookmarks.restore_default_bookmarks", false);\n';

// https://developer.mozilla.org/en-US/docs/Command_Line_Options
var FirefoxBrowser = function(id) {
  BaseBrowser.apply(this, arguments);

  this._start = function(url) {
    var self = this;
    var command = this._getCommand();
    var errorOutput = '';

    var p = spawn(command, ['-CreateProfile', 'testacular-' + id + ' ' + self._tempDir, '-no-remote']);

    p.stderr.on('data', function(data) {
      errorOutput += data.toString();
    });

    p.on('close', function() {
      var match = /at\s\'(.*)[\/\\]prefs\.js\'/.exec(errorOutput);

      if (match) {
        self._tempDir = match[1];
      }

      fs.createWriteStream(self._tempDir + '/prefs.js', {flags: 'a'}).write(PREFS);
      self._execCommand(command, [url, '-profile', self._tempDir, '-no-remote']);
    });
  };
};

FirefoxBrowser.prototype = {
  name: 'Firefox',

  DEFAULT_CMD: {
    linux: 'firefox',
    darwin: '/Applications/Firefox.app/Contents/MacOS/firefox-bin',
    win32: process.env.ProgramFiles + '\\Mozilla Firefox\\firefox.exe'
  },
  ENV_CMD: 'FIREFOX_BIN'
};

// PUBLISH
module.exports = FirefoxBrowser;
<|endoftext|>


<commit_before><commit_msg>Fix Positive Rate<commit_after><|endoftext|>