<commit_before>/**
 * Copyright 2013-2015, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @emails react-core
 */

'use strict';

// NOTE: We're explicitly not using JSX in this file. This is intended to test
// classic JS without JSX.

var React;
var ReactDOM;
var ReactTestUtils;

describe('ReactElement', function() {
  var ComponentClass;
  var originalSymbol;

  beforeEach(function() {
    require('mock-modules').dumpCache();

    // Delete the native Symbol if we have one to ensure we test the
    // unpolyfilled environment.
    originalSymbol = global.Symbol;
    global.Symbol = undefined;

    React = require('React');
    ReactDOM = require('ReactDOM');
    ReactTestUtils = require('ReactTestUtils');
    ComponentClass = React.createClass({
      render: function() {
        return React.createElement('div');
      },
    });
  });

  afterEach(function() {
    global.Symbol = originalSymbol;
  });

  it('uses the fallback value when in an environment without Symbol', function() {
    expect(
.$$typeof).toBe(0xeac7);
  });

  it('returns a complete element according to spec', function() {
    var element = React.createFactory(ComponentClass)();
    expect(element.type).toBe(ComponentClass);
    expect(element.key).toBe(null);
    expect(element.ref).toBe(null);
    var expectation = {};
    Object.freeze(expectation);
    expect(element.props).toEqual(expectation);
  });

  it('allows a string to be passed as the type', function() {
    var element = React.createFactory('div')();
    expect(element.type).toBe('div');
    expect(element.key).toBe(null);
    expect(element.ref).toBe(null);
    var expectation = {};
    Object.freeze(expectation);
    expect(element.props).toEqual(expectation);
  });

  it('returns an immutable element', function() {
    var element = React.createFactory(ComponentClass)();
    expect(() => element.type = 'div').toThrow();
  });

  it('does not reuse the original config object', function() {
    var config = {foo: 1};
    var element = React.createFactory(ComponentClass)(config);
    expect(element.props.foo).toBe(1);
    config.foo = 2;
    expect(element.props.foo).toBe(1);
  });

  it('extracts key and ref from the config', function() {
    var element = React.createFactory(ComponentClass)({
      key: '12',
      ref: '34',
      foo: '56',
    });
    expect(element.type).toBe(ComponentClass);
    expect(element.key).toBe('12');
    expect(element.ref).toBe('34');
    var expectation = {foo:'56'};
    Object.freeze(expectation);
    expect(element.props).toEqual(expectation);
  });

  it('coerces the key to a string', function() {
    var element = React.createFactory(ComponentClass)({
      key: 12,
      foo: '56',
    });
    expect(element.type).toBe(ComponentClass);
    expect(element.key).toBe('12');
    expect(element.ref).toBe(null);
    var expectation = {foo:'56'};
    Object.freeze(expectation);
    expect(element.props).toEqual(expectation);
  });

  it('preserves the owner on the element', function() {
    var Component = React.createFactory(ComponentClass);
    var element;

    var Wrapper = React.createClass({
      render: function() {
        element = Component();
        return element;
      },
    });

    var instance = ReactTestUtils.renderIntoDocument(
      React.createElement(Wrapper)
    );

    expect(element._owner.getPublicInstance()).toBe(instance);
  });

  it('merges an additional argument onto the children prop', function() {
    spyOn(console, 'error');
    var a = 1;
    var element = React.createFactory(ComponentClass)({
      children: 'text',
    }, a);
    expect(element.props.children).toBe(a);
    expect(console.error.argsForCall.length).toBe(0);
  });

  it('does not override children if no rest args are provided', function() {
    spyOn(console, 'error');
    var element = React.createFactory(ComponentClass)({
      children: 'text',
    });
    expect(element.props.children).toBe('text');
    expect(console.error.argsForCall.length).toBe(0);
  });

  it('overrides children if null is provided as an argument', function() {
    spyOn(console, 'error');
    var element = React.createFactory(ComponentClass)({
      children: 'text',
    }, null);
    expect(element.props.children).toBe(null);
    expect(console.error.argsForCall.length).toBe(0);
  });

  it('merges rest arguments onto the children prop in an array', function() {
    spyOn(console, 'error');
    var a = 1;
    var b = 2;
    var c = 3;
    var element = React.createFactory(ComponentClass)(null, a, b, c);
    expect(element.props.children).toEqual([1, 2, 3]);
    expect(console.error.argsForCall.length).toBe(0);
  });

  it('allows static methods to be called using the type property', function() {
    spyOn(console, 'error');

    var StaticMethodComponentClass = React.createClass({
      statics: {
        someStaticMethod: function() {
          return 'someReturnValue';
        },
      },
      getInitialState: function() {
        return {valueToReturn: 'hi'};
      },
      render: function() {
        return React.createElement('div');
      },
    });

    var element = React.createElement(StaticMethodComponentClass);
    expect(element.type.someStaticMethod()).toBe('someReturnValue');
    expect(console.error.argsForCall.length).toBe(0);
  });

  it('identifies valid elements', function() {
    var Component = React.createClass({
      render: function() {
        return React.createElement('div');
      },
    });

    expect(React.isValidElement(React.createElement('div')))
      .toEqual(true);
    expect(React.isValidElement(React.createElement(Component)))
      .toEqual(true);

    expect(React.isValidElement(null)).toEqual(false);
    expect(React.isValidElement(true)).toEqual(false);
    expect(React.isValidElement({})).toEqual(false);
    expect(React.isValidElement('string')).toEqual(false);
    expect(React.isValidElement(React.DOM.div)).toEqual(false);
    expect(React.isValidElement(Component)).toEqual(false);
    expect(React.isValidElement({ type: 'div', props: {} })).toEqual(false);

    var jsonElement = JSON.stringify(React.createElement('div'));
    expect(React.isValidElement(JSON.parse(jsonElement))).toBe(true);
  });

  it('allows the use of PropTypes validators in statics', function() {
    // TODO: This test was added to cover a special case where we proxied
    // methods. However, we don't do that any more so this test can probably
    // be removed. Leaving it in classic as a safety precausion.
    var Component = React.createClass({
      render: () => null,
      statics: {
        specialType: React.PropTypes.shape({monkey: React.PropTypes.any}),
      },
    });

    expect(typeof Component.specialType).toBe('function');
    expect(typeof Component.specialType.isRequired).toBe('function');
  });

  it('is indistinguishable from a plain object', function() {
    var element = React.createElement('div', {className: 'foo'});
    var object = {};
    expect(element.constructor).toBe(object.constructor);
  });

  it('should use default prop value when removing a prop', function() {
    var Component = React.createClass({
      getDefaultProps: function() {
        return {fruit: 'persimmon'};
      },
      render: function() {
        return React.createElement('span');
      },
    });

    var container = document.createElement('div');
    var instance = ReactDOM.render(
      React.createElement(Component, {fruit: 'mango'}),
      container
    );
    expect(instance.props.fruit).toBe('mango');

    ReactDOM.render(React.createElement(Component), container);
    expect(instance.props.fruit).toBe('persimmon');
  });

  it('should normalize props with default values', function() {
    var Component = React.createClass({
      getDefaultProps: function() {
        return {prop: 'testKey'};
      },
      render: function() {
        return React.createElement('span', null, this.props.prop);
      },
    });

    var instance = ReactTestUtils.renderIntoDocument(
      React.createElement(Component)
    );
    expect(instance.props.prop).toBe('testKey');

    var inst2 = ReactTestUtils.renderIntoDocument(
      React.createElement(Component, {prop: null})
    );
    expect(inst2.props.prop).toBe(null);
  });

  it('throws when changing a prop (in dev) after element creation', function() {
    var Outer = React.createClass({
      render: function() {
        var el =
;

        expect(function() {
          el.props.className = 'quack';
        }).toThrow();
        expect(el.props.className).toBe('moo');

        return el;
      },
    });
    var outer = ReactTestUtils.renderIntoDocument(<Outer color="orange" />);
    expect(ReactDOM.findDOMNode(outer).className).toBe('moo');
  });

  it('throws when adding a prop (in dev) after element creation', function() {
    var container = document.createElement('div');
    var Outer = React.createClass({
      getDefaultProps: () => ({sound: 'meow'}),
      render: function() {
        var el =
{this.props.sound}
;

        expect(function() {
          el.props.className = 'quack';
        }).toThrow();

        expect(el.props.className).toBe(undefined);

        return el;
      },
    });
    var outer = ReactDOM.render(<Outer />, container);
    expect(ReactDOM.findDOMNode(outer).textContent).toBe('meow');
    expect(ReactDOM.findDOMNode(outer).className).toBe('');
  });

  it('does not warn for NaN props', function() {
    spyOn(console, 'error');
    var Test = React.createClass({
      render: function() {
        return
;
      },
    });
    var test = ReactTestUtils.renderIntoDocument(<Test value={+undefined} />);
    expect(test.props.value).toBeNaN();
    expect(console.error.argsForCall.length).toBe(0);
  });

  it('identifies elements, but not JSON, if Symbols are supported', function() {
    // Rudimentary polyfill
    // Once all jest engines support Symbols natively we can swap this to test
    // WITH native Symbols by default.
    var REACT_ELEMENT_TYPE = function() {}; // fake Symbol
    var OTHER_SYMBOL = function() {}; // another fake Symbol
    global.Symbol = function(name) {
      return OTHER_SYMBOL;
    };
    global.Symbol.for = function(key) {
      if (key === 'react.element') {
        return REACT_ELEMENT_TYPE;
      }
      return OTHER_SYMBOL;
    };

    require('mock-modules').dumpCache();

    React = require('React');

    var Component = React.createClass({
      render: function() {
        return React.createElement('div');
      },
    });

    expect(React.isValidElement(React.createElement('div')))
      .toEqual(true);
    expect(React.isValidElement(React.createElement(Component)))
      .toEqual(true);

    expect(React.isValidElement(null)).toEqual(false);
    expect(React.isValidElement(true)).toEqual(false);
    expect(React.isValidElement({})).toEqual(false);
    expect(React.isValidElement('string')).toEqual(false);
    expect(React.isValidElement(React.DOM.div)).toEqual(false);
    expect(React.isValidElement(Component)).toEqual(false);
    expect(React.isValidElement({ type: 'div', props: {} })).toEqual(false);

    var jsonElement = JSON.stringify(React.createElement('div'));
    expect(React.isValidElement(JSON.parse(jsonElement))).toBe(false);
  });

});
<commit_msg>- Added tests to compare testing of components using different types of element creation<commit_after>/**
 * Copyright 2013-2015, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @emails react-core
 */

'use strict';

// NOTE: We're explicitly not using JSX in this file. This is intended to test
// classic JS without JSX.

var React;
var ReactDOM;
var ReactTestUtils;

describe('ReactElement', function() {
  var ComponentClass;
  var originalSymbol;

  beforeEach(function() {
    require('mock-modules').dumpCache();

    // Delete the native Symbol if we have one to ensure we test the
    // unpolyfilled environment.
    originalSymbol = global.Symbol;
    global.Symbol = undefined;

    React = require('React');
    ReactDOM = require('ReactDOM');
    ReactTestUtils = require('ReactTestUtils');
    ComponentClass = React.createClass({
      render: function() {
        return React.createElement('div');
      },
    });
  });

  afterEach(function() {
    global.Symbol = originalSymbol;
  });

  it('uses the fallback value when in an environment without Symbol', function() {
    expect(
.$$typeof).toBe(0xeac7);
  });

  it('returns a complete element according to spec', function() {
    var element = React.createFactory(ComponentClass)();
    expect(element.type).toBe(ComponentClass);
    expect(element.key).toBe(null);
    expect(element.ref).toBe(null);
    var expectation = {};
    Object.freeze(expectation);
    expect(element.props).toEqual(expectation);
  });

  it('allows a string to be passed as the type', function() {
    var element = React.createFactory('div')();
    expect(element.type).toBe('div');
    expect(element.key).toBe(null);
    expect(element.ref).toBe(null);
    var expectation = {};
    Object.freeze(expectation);
    expect(element.props).toEqual(expectation);
  });

  it('returns an immutable element', function() {
    var element = React.createFactory(ComponentClass)();
    expect(() => element.type = 'div').toThrow();
  });

  it('does not reuse the original config object', function() {
    var config = {foo: 1};
    var element = React.createFactory(ComponentClass)(config);
    expect(element.props.foo).toBe(1);
    config.foo = 2;
    expect(element.props.foo).toBe(1);
  });

  it('extracts key and ref from the config', function() {
    var element = React.createFactory(ComponentClass)({
      key: '12',
      ref: '34',
      foo: '56',
    });
    expect(element.type).toBe(ComponentClass);
    expect(element.key).toBe('12');
    expect(element.ref).toBe('34');
    var expectation = {foo:'56'};
    Object.freeze(expectation);
    expect(element.props).toEqual(expectation);
  });

  it('coerces the key to a string', function() {
    var element = React.createFactory(ComponentClass)({
      key: 12,
      foo: '56',
    });
    expect(element.type).toBe(ComponentClass);
    expect(element.key).toBe('12');
    expect(element.ref).toBe(null);
    var expectation = {foo:'56'};
    Object.freeze(expectation);
    expect(element.props).toEqual(expectation);
  });

  it('preserves the owner on the element', function() {
    var Component = React.createFactory(ComponentClass);
    var element;

    var Wrapper = React.createClass({
      render: function() {
        element = Component();
        return element;
      },
    });

    var instance = ReactTestUtils.renderIntoDocument(
      React.createElement(Wrapper)
    );

    expect(element._owner.getPublicInstance()).toBe(instance);
  });

  it('merges an additional argument onto the children prop', function() {
    spyOn(console, 'error');
    var a = 1;
    var element = React.createFactory(ComponentClass)({
      children: 'text',
    }, a);
    expect(element.props.children).toBe(a);
    expect(console.error.argsForCall.length).toBe(0);
  });

  it('does not override children if no rest args are provided', function() {
    spyOn(console, 'error');
    var element = React.createFactory(ComponentClass)({
      children: 'text',
    });
    expect(element.props.children).toBe('text');
    expect(console.error.argsForCall.length).toBe(0);
  });

  it('overrides children if null is provided as an argument', function() {
    spyOn(console, 'error');
    var element = React.createFactory(ComponentClass)({
      children: 'text',
    }, null);
    expect(element.props.children).toBe(null);
    expect(console.error.argsForCall.length).toBe(0);
  });

  it('merges rest arguments onto the children prop in an array', function() {
    spyOn(console, 'error');
    var a = 1;
    var b = 2;
    var c = 3;
    var element = React.createFactory(ComponentClass)(null, a, b, c);
    expect(element.props.children).toEqual([1, 2, 3]);
    expect(console.error.argsForCall.length).toBe(0);
  });

  it('allows static methods to be called using the type property', function() {
    spyOn(console, 'error');

    var StaticMethodComponentClass = React.createClass({
      statics: {
        someStaticMethod: function() {
          return 'someReturnValue';
        },
      },
      getInitialState: function() {
        return {valueToReturn: 'hi'};
      },
      render: function() {
        return React.createElement('div');
      },
    });

    var element = React.createElement(StaticMethodComponentClass);
    expect(element.type.someStaticMethod()).toBe('someReturnValue');
    expect(console.error.argsForCall.length).toBe(0);
  });

  it('identifies valid elements', function() {
    var Component = React.createClass({
      render: function() {
        return React.createElement('div');
      },
    });

    expect(React.isValidElement(React.createElement('div')))
      .toEqual(true);
    expect(React.isValidElement(React.createElement(Component)))
      .toEqual(true);

    expect(React.isValidElement(null)).toEqual(false);
    expect(React.isValidElement(true)).toEqual(false);
    expect(React.isValidElement({})).toEqual(false);
    expect(React.isValidElement('string')).toEqual(false);
    expect(React.isValidElement(React.DOM.div)).toEqual(false);
    expect(React.isValidElement(Component)).toEqual(false);
    expect(React.isValidElement({ type: 'div', props: {} })).toEqual(false);

    var jsonElement = JSON.stringify(React.createElement('div'));
    expect(React.isValidElement(JSON.parse(jsonElement))).toBe(true);
  });

  it('allows the use of PropTypes validators in statics', function() {
    // TODO: This test was added to cover a special case where we proxied
    // methods. However, we don't do that any more so this test can probably
    // be removed. Leaving it in classic as a safety precausion.
    var Component = React.createClass({
      render: () => null,
      statics: {
        specialType: React.PropTypes.shape({monkey: React.PropTypes.any}),
      },
    });

    expect(typeof Component.specialType).toBe('function');
    expect(typeof Component.specialType.isRequired).toBe('function');
  });

  it('is indistinguishable from a plain object', function() {
    var element = React.createElement('div', {className: 'foo'});
    var object = {};
    expect(element.constructor).toBe(object.constructor);
  });

  it('should use default prop value when removing a prop', function() {
    var Component = React.createClass({
      getDefaultProps: function() {
        return {fruit: 'persimmon'};
      },
      render: function() {
        return React.createElement('span');
      },
    });

    var container = document.createElement('div');
    var instance = ReactDOM.render(
      React.createElement(Component, {fruit: 'mango'}),
      container
    );
    expect(instance.props.fruit).toBe('mango');

    ReactDOM.render(React.createElement(Component), container);
    expect(instance.props.fruit).toBe('persimmon');
  });

  it('should normalize props with default values', function() {
    var Component = React.createClass({
      getDefaultProps: function() {
        return {prop: 'testKey'};
      },
      render: function() {
        return React.createElement('span', null, this.props.prop);
      },
    });

    var instance = ReactTestUtils.renderIntoDocument(
      React.createElement(Component)
    );
    expect(instance.props.prop).toBe('testKey');

    var inst2 = ReactTestUtils.renderIntoDocument(
      React.createElement(Component, {prop: null})
    );
    expect(inst2.props.prop).toBe(null);
  });

  it('throws when changing a prop (in dev) after element creation', function() {
    var Outer = React.createClass({
      render: function() {
        var el =
;

        expect(function() {
          el.props.className = 'quack';
        }).toThrow();
        expect(el.props.className).toBe('moo');

        return el;
      },
    });
    var outer = ReactTestUtils.renderIntoDocument(<Outer color="orange" />);
    expect(ReactDOM.findDOMNode(outer).className).toBe('moo');
  });

  it('throws when adding a prop (in dev) after element creation', function() {
    var container = document.createElement('div');
    var Outer = React.createClass({
      getDefaultProps: () => ({sound: 'meow'}),
      render: function() {
        var el =
{this.props.sound}
;

        expect(function() {
          el.props.className = 'quack';
        }).toThrow();

        expect(el.props.className).toBe(undefined);

        return el;
      },
    });
    var outer = ReactDOM.render(<Outer />, container);
    expect(ReactDOM.findDOMNode(outer).textContent).toBe('meow');
    expect(ReactDOM.findDOMNode(outer).className).toBe('');
  });

  it('does not warn for NaN props', function() {
    spyOn(console, 'error');
    var Test = React.createClass({
      render: function() {
        return
;
      },
    });
    var test = ReactTestUtils.renderIntoDocument(<Test value={+undefined} />);
    expect(test.props.value).toBeNaN();
    expect(console.error.argsForCall.length).toBe(0);
  });

  it('identifies elements, but not JSON, if Symbols are supported', function() {
    // Rudimentary polyfill
    // Once all jest engines support Symbols natively we can swap this to test
    // WITH native Symbols by default.
    var REACT_ELEMENT_TYPE = function() {}; // fake Symbol
    var OTHER_SYMBOL = function() {}; // another fake Symbol
    global.Symbol = function(name) {
      return OTHER_SYMBOL;
    };
    global.Symbol.for = function(key) {
      if (key === 'react.element') {
        return REACT_ELEMENT_TYPE;
      }
      return OTHER_SYMBOL;
    };

    require('mock-modules').dumpCache();

    React = require('React');

    var Component = React.createClass({
      render: function() {
        return React.createElement('div');
      },
    });

    expect(React.isValidElement(React.createElement('div')))
      .toEqual(true);
    expect(React.isValidElement(React.createElement(Component)))
      .toEqual(true);

    expect(React.isValidElement(null)).toEqual(false);
    expect(React.isValidElement(true)).toEqual(false);
    expect(React.isValidElement({})).toEqual(false);
    expect(React.isValidElement('string')).toEqual(false);
    expect(React.isValidElement(React.DOM.div)).toEqual(false);
    expect(React.isValidElement(Component)).toEqual(false);
    expect(React.isValidElement({ type: 'div', props: {} })).toEqual(false);

    var jsonElement = JSON.stringify(React.createElement('div'));
    expect(React.isValidElement(JSON.parse(jsonElement))).toBe(false);
  });

});

describe('comparing jsx vs .createFactory() vs .createElement()', function() {
  var Child, mocks;

  beforeEach(function() {
    require('mock-modules').dumpCache();
    mocks = require('mocks');
    React = require('React');
    ReactDOM = require('ReactDOM');
    ReactTestUtils = require('ReactTestUtils');

    var metaData = mocks.getMetadata(React.createClass({
      render: function() {
        return React.createElement('div');
      },
    }));

    Child = mocks.generateFromMetadata(metaData);

  });

  describe('when using jsx only', function() {
    var Parent, instance;
    beforeEach(function() {
      Parent = React.createClass({
        render: function() {
          return (

              <Child ref="child" foo="foo value">children value</Child>

          );
        },
      });
      instance = ReactTestUtils.renderIntoDocument(<Parent/>);
    });

    it('should scry children but cannot', function() {
      var children = ReactTestUtils.scryRenderedComponentsWithType(instance, Child);
      expect(children.length).toBe(1);
    });

    it('does not maintain refs', function() {
      expect(instance.refs.child).not.toBeUndefined();
    });

    it('can capture Child instantiation calls', function() {
      expect(Child.mock.calls[0][0]).toEqual({ foo: 'foo value', children: 'children value' });
    });
  });

  describe('when using parent that uses .createFactory()', function() {
    var factory, instance;
    beforeEach(function() {
      var childFactory = React.createFactory(Child);
      var Parent = React.createClass({
        render: function() {
          return React.DOM.div({}, childFactory({ ref: 'child', foo: 'foo value' }, 'children value'));
        },
      });
      factory = React.createFactory(Parent);
      instance = ReactTestUtils.renderIntoDocument(factory());
    });

    it('can properly scry children', function() {
      var children = ReactTestUtils.scryRenderedComponentsWithType(instance, Child);
      expect(children.length).toBe(1);
    });

    it('does not maintain refs', function() {
      expect(instance.refs.child).not.toBeUndefined();
    });

    it('can capture Child instantiation calls', function() {
      expect(Child.mock.calls[0][0]).toEqual({ foo: 'foo value', children: 'children value' });
    });
  });

  describe('when using parent that uses .createElement()', function() {
    var factory, instance;
    beforeEach(function() {
      var Parent = React.createClass({
        render: function() {
          return React.DOM.div({}, React.createElement(Child, { ref: 'child', foo: 'foo value' }, 'children value'));
        },
      });
      factory = React.createFactory(Parent);
      instance = ReactTestUtils.renderIntoDocument(factory());
    });

    it('should scry children but cannot', function() {
      var children = ReactTestUtils.scryRenderedComponentsWithType(instance, Child);
      expect(children.length).toBe(1);
    });

    it('does not maintain refs', function() {
      expect(instance.refs.child).not.toBeUndefined();
    });

    it('can capture Child instantiation calls', function() {
      expect(Child.mock.calls[0][0]).toEqual({ foo: 'foo value', children: 'children value' });
    });
  });
});
<|endoftext|>


<commit_before>/*
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

'use strict';

var _ = require('lodash');
var spawn = require('child_process').spawn;
var execSync = require('child_process').execSync;
var psTree = require('ps-tree');

module.exports = function() {
  var baseCmd = 'test -f ~/.bashrc && source ~/.bashrc; test -f ~/.bash_profile && source ~/.bash_profile; ';
  var isWin = /^win/.test(process.platform);

  var handleIpAddress = function(container, cmd) {
    var ipAddress;

    ipAddress = container.specific.ipAddress || '127.0.0.1';
    cmd = cmd.replace(/__TARGETIP__/g, ipAddress);
    return cmd;
  };

  var generateEnvironment = function(containerEnv) {
    var envArgs = ' ';
    _.each(_.keys(containerEnv), function(key) {
      if (isWin) {
        envArgs += 'set ' + key + '=' + containerEnv[key] + '&&';
      }
      else {
        envArgs += 'export ' + key + '=' + containerEnv[key] + ';';
      }
    });
    return envArgs;
  };

  var run = function(mode, container, exitCb, cb) {
    var toExec;
    var cmd;
    var cwd;
    var env;
    var child = {};
    var envArgs = '';
    var called = false;

    cmd = container.specific.execute.exec;
    cwd = container.specific.path;

    if (container.specific && container.specific.environment) {
      envArgs = generateEnvironment(container.specific.environment);
    }

    if (isWin) {
      toExec = envArgs + ' ' + cmd;
    }
    else {
      toExec = baseCmd + envArgs + ' exec ' + cmd;
    }

    toExec = handleIpAddress(container, toExec);

    env = Object.create(process.env);
    if (mode !== 'preview') {
      if (isWin) {
        child = spawn(process.env.comspec, ['/c', toExec], {cwd: cwd, env: env, stdio: [0, 'pipe', 'pipe'], detached: false,});
      }
      else {
        child = spawn('/bin/bash', ['-c', toExec], {cwd: cwd, env: env, stdio: [0, 'pipe', 'pipe'], detached: false,});
      }
      child.unref();

      child.on('error', function(err) {
        if (!called) {
          called = true;
          exitCb(child.pid, container.name, err);
        }
      });

      child.on('exit', function(code) {
        if (!called) {
          called = true;
          exitCb(child.pid, container.name, code);
        }
      });
    }
    else {
      child.detail = { cmd: cmd,
                       environment: container.specific.environment,
                       cwd: cwd };
    }

    cb(null, child);
  };

  var start = function(mode, container, config, exitCb, cb) {
    if (container && container.specific && container.specific.execute && container.specific.execute.exec) {
      if (container.type === 'docker' && !config.runDocker) {
        console.log('docker disabled, skipping: ' + container.specific.execute.exec);
        cb();
      }
      else {
        run(mode, container, exitCb, function(err, child) {
          cb(err, child);
        });
      }
    }
    else {
      if (container.name !== '__proxy') {
        console.log('warning: ' + container.name + ' not started, missing execute statement');
      }
      cb();
    }
  };

  var getContainerId = function(psOutput, container) {
    var lines = psOutput.split('\n');
    var re = new RegExp('^([a-f0-9]+)\\s+' + container.specific.execute.image + '.*');
    var id = null;
    var match;

    _.each(lines, function(line) {
      match = re.exec(line);
      if (match) {
        id = match[1];
      }
    });
    return id;
  };

  var stop = function stop(container, pid, cb) {
    var psOutput;
    var id;

    if (pid) {
      try {
        if (container.type === 'docker') {
          if (!psOutput) {
            psOutput = execSync('docker ps').toString();
          }
          id = getContainerId(psOutput, container);
          if (id) {
            execSync('docker kill ' + id);
          }
        }
        psTree(pid, function(err, children) {
          spawn('kill', ['-9'].concat(children.map(function (p) { return p.PID; })));
        });
        process.kill(pid, 'SIGKILL');
      }
      catch (e) {
        console.log(e);
      }
    }
    cb(null);
  };

  return {
    start: start,
    stop: stop,
  };
};

<commit_msg>windows support process kill<commit_after>/*
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

'use strict';

var _ = require('lodash');
var spawn = require('child_process').spawn;
var execSync = require('child_process').execSync;
var psTree = require('ps-tree');

module.exports = function() {
  var baseCmd = 'test -f ~/.bashrc && source ~/.bashrc; test -f ~/.bash_profile && source ~/.bash_profile; ';
  var isWin = /^win/.test(process.platform);

  var handleIpAddress = function(container, cmd) {
    var ipAddress;

    ipAddress = container.specific.ipAddress || '127.0.0.1';
    cmd = cmd.replace(/__TARGETIP__/g, ipAddress);
    return cmd;
  };

  var generateEnvironment = function(containerEnv) {
    var envArgs = ' ';
    _.each(_.keys(containerEnv), function(key) {
      if (isWin) {
        envArgs += 'set ' + key + '=' + containerEnv[key] + '&&';
      }
      else {
        envArgs += 'export ' + key + '=' + containerEnv[key] + ';';
      }
    });
    return envArgs;
  };

  var run = function(mode, container, exitCb, cb) {
    var toExec;
    var cmd;
    var cwd;
    var env;
    var child = {};
    var envArgs = '';
    var called = false;

    cmd = container.specific.execute.exec;
    cwd = container.specific.path;

    if (container.specific && container.specific.environment) {
      envArgs = generateEnvironment(container.specific.environment);
    }

    if (isWin) {
      toExec = envArgs + ' ' + cmd;
    }
    else {
      toExec = baseCmd + envArgs + ' exec ' + cmd;
    }

    toExec = handleIpAddress(container, toExec);

    env = Object.create(process.env);
    if (mode !== 'preview') {
      if (isWin) {
        child = spawn(process.env.comspec, ['/c', toExec], {cwd: cwd, env: env, stdio: [0, 'pipe', 'pipe'], detached: false,});
      }
      else {
        child = spawn('/bin/bash', ['-c', toExec], {cwd: cwd, env: env, stdio: [0, 'pipe', 'pipe'], detached: false,});
      }
      child.unref();

      child.on('error', function(err) {
        if (!called) {
          called = true;
          exitCb(child.pid, container.name, err);
        }
      });

      child.on('exit', function(code) {
        if (!called) {
          called = true;
          exitCb(child.pid, container.name, code);
        }
      });
    }
    else {
      child.detail = { cmd: cmd,
                       environment: container.specific.environment,
                       cwd: cwd };
    }

    cb(null, child);
  };

  var start = function(mode, container, config, exitCb, cb) {
    if (container && container.specific && container.specific.execute && container.specific.execute.exec) {
      if (container.type === 'docker' && !config.runDocker) {
        console.log('docker disabled, skipping: ' + container.specific.execute.exec);
        cb();
      }
      else {
        run(mode, container, exitCb, function(err, child) {
          cb(err, child);
        });
      }
    }
    else {
      if (container.name !== '__proxy') {
        console.log('warning: ' + container.name + ' not started, missing execute statement');
      }
      cb();
    }
  };

  var getContainerId = function(psOutput, container) {
    var lines = psOutput.split('\n');
    var re = new RegExp('^([a-f0-9]+)\\s+' + container.specific.execute.image + '.*');
    var id = null;
    var match;

    _.each(lines, function(line) {
      match = re.exec(line);
      if (match) {
        id = match[1];
      }
    });
    return id;
  };

  var stop = function stop(container, pid, cb) {
    var psOutput;
    var id;

    if (pid) {
      try {
        if (container.type === 'docker') {
          if (!psOutput) {
            psOutput = execSync('docker ps').toString();
          }
          id = getContainerId(psOutput, container);
          if (id) {
            execSync('docker kill ' + id);
          }
        }
        if (isWin) {
          var procs = '' + execSync('wmic process where(ParentProcessId=' + pid + ') get ProcessId');
          var pids = procs.trim().split('\r\n');
          if (pids.length > 1) {
            process.kill(pids[1], 'SIGKILL');
          }
        }
        else {
          psTree(pid, function(err, children) {
            spawn('kill', ['-9'].concat(children.map(function (p) { return p.PID; })));
          });
        }
        process.kill(pid, 'SIGKILL');
      }
      catch (e) {
        console.log(e);
      }
    }
    cb(null);
  };

  return {
    start: start,
    stop: stop,
  };
};

<|endoftext|>


<commit_before>import moment from 'moment';

import locations from '../core/locations';

import Event from '../models/event';
import Place from '../models/place';

import EventPage from '../pages/event';
import EventListPage from '../pages/event-list';
import PlacePage from '../pages/place';
import PlaceListPage from '../pages/place-list';
import NotFoundPage from '../pages/not-found';

import {Redirect, Render, NotFound} from './response';

export function index(app) {
  const location = app.settings.get('location');
  return Redirect(app.resolver.reverse('event-list', {location}));
}

export function location(app, {location}) {
  if (!locations.has(location)) return notFound(app);
  return Redirect(app.resolver.reverse('event-list', {location}));
}

export function eventList(app, {location, date}) {
  location = locations.get(location);
  date = date ? moment.tz(date, location.timezone) : null;
  if (!location) return notFound(app);

  const feed = app.api.getEventsFeed(location, date);
  const page = new EventListPage({app, location, date, feed});
  return Render({page, location});
}

export function event(app, {id}) {
  return app.api
    .fetchEvent(id)
    .then(data => {
      const event = new Event(data);
      const page = new EventPage({app, event});
      const location = event.getLocation();
      return Render({page, location});
    })
    .catch(error => error.response.status == 404 ? notFound(app) : undefined);
}

export function placeList(app, {location}) {
  location = locations.get(location);
  if (!location) return notFound(app);

  const feed = app.api.getPlacesFeed(location);
  const page = new PlaceListPage({app, location, feed});
  return Render({page, location});
}

export function place(app, {id}) {
  return app.api
    .fetchPlace(id)
    .then(data => {
      const place = new Place(data);
      const page = new PlacePage({app, place});
      const location = place.getLocation();
      return Render({page, location});
    })
    .catch(error => error.response.status == 404 ? notFound(app) : undefined);
}

export function notFound(app) {
  const page = new NotFoundPage({app});
  return NotFound({page});
}
<commit_msg>Use a shorter import path<commit_after>import moment from 'moment';

import locations from './locations';

import Event from '../models/event';
import Place from '../models/place';

import EventPage from '../pages/event';
import EventListPage from '../pages/event-list';
import PlacePage from '../pages/place';
import PlaceListPage from '../pages/place-list';
import NotFoundPage from '../pages/not-found';

import {Redirect, Render, NotFound} from './response';

export function index(app) {
  const location = app.settings.get('location');
  return Redirect(app.resolver.reverse('event-list', {location}));
}

export function location(app, {location}) {
  if (!locations.has(location)) return notFound(app);
  return Redirect(app.resolver.reverse('event-list', {location}));
}

export function eventList(app, {location, date}) {
  location = locations.get(location);
  date = date ? moment.tz(date, location.timezone) : null;
  if (!location) return notFound(app);

  const feed = app.api.getEventsFeed(location, date);
  const page = new EventListPage({app, location, date, feed});
  return Render({page, location});
}

export function event(app, {id}) {
  return app.api
    .fetchEvent(id)
    .then(data => {
      const event = new Event(data);
      const page = new EventPage({app, event});
      const location = event.getLocation();
      return Render({page, location});
    })
    .catch(error => error.response.status == 404 ? notFound(app) : undefined);
}

export function placeList(app, {location}) {
  location = locations.get(location);
  if (!location) return notFound(app);

  const feed = app.api.getPlacesFeed(location);
  const page = new PlaceListPage({app, location, feed});
  return Render({page, location});
}

export function place(app, {id}) {
  return app.api
    .fetchPlace(id)
    .then(data => {
      const place = new Place(data);
      const page = new PlacePage({app, place});
      const location = place.getLocation();
      return Render({page, location});
    })
    .catch(error => error.response.status == 404 ? notFound(app) : undefined);
}

export function notFound(app) {
  const page = new NotFoundPage({app});
  return NotFound({page});
}
<|endoftext|>


<commit_before>import Ember from 'ember';

export default Ember.Component.extend({
  classNames: ['categories-list'],
  sortByName: ['name'],

  sortedCategories: Ember.computed.sort('categories', 'sortByName'),
});
<commit_msg>add categories-list docs<commit_after>import Ember from 'ember';

/**
 * `categories-list` composes the list of categories
 *
 * ## default usage
 *
 * ```handlebars
 * {{categories-list categories=listOfCategories}}
 * ```
 *
 * @class categories-list
 * @module Component
 * @extends Ember.Component
 */
export default Ember.Component.extend({
  classNames: ['categories-list'],

  /**
   * An array of properties used to sort the list of categories.
   *
   * @property sortByName
   * @type Array
   */
  sortByName: ['name'],

  /**
   * `sortedCategories` consumes the list of categories and sorts them based on
   * the `sortByName` property.
   *
   * @property sortedCategories
   * @type Array
   */
  sortedCategories: Ember.computed.sort('categories', 'sortByName'),
});
<|endoftext|>


<commit_before>import sanitizeHtml from 'sanitize-html'
import prettyDate from 'pretty-date'
import truncate from 'html-truncate'
import linkify from './linkify'
import moment from 'moment-timezone'
import marked from 'marked'

export function sanitize (text) {
  if (!text) return ''

  // remove leading   (a side-effect of contenteditable)
  var strippedText = text.replace(/
 /gi, '
')

  return sanitizeHtml(strippedText, {
    allowedTags: ['a', 'p', 'br', 'ul', 'ol', 'li', 'strong', 'em'],
    allowedAttributes: {
      'a': ['href', 'data-user-id']
    },

    // remove empty paragraphs
    exclusiveFilter: function (frame) {
      return frame.tag === 'p' && !frame.text.trim()
    }
  })
}

export function present (text, opts) {
  if (!text) return '

'

  // wrap in a
 tag
  if (text.substring(0, 3) !== '
') text = `<p>${text}</p>`

  // make links and hashtags
  text = linkify(text)

  if (opts && opts.maxlength) text = truncate(text, opts.maxlength)

  return text
}

export function humanDate (date, short) {
  var ret = prettyDate.format(typeof date === 'string' ? new Date(date) : date)
  if (short) ret = ret.replace(' ago', '')
  return ret
}

const sameDay = (t1, t2) =>
  t1.getFullYear() === t2.getFullYear() &&
  t1.getMonth() === t2.getMonth() &&
  t1.getDate() === t2.getDate()

export function timeRange (start, end) {
  let startText = moment(start).calendar(null, {
    sameElse: 'dddd, MMM D, YYYY [at] h:mm A'
  })
  if (!end) {
    return startText
  } else if (sameDay(start, end)) {
    startText = startText.replace(' at ', ' from ')
    let endText = moment(end).format('h:mm A')
    return `${startText} to ${endText}`
  } else {
    return `${startText} to ${moment(end).calendar()}`
  }
}

export function timeRangeFull (start, end) {
  if (!end) {
    return moment(start).format('LLLL')
  } else {
    return moment(start).format('LLLL') + ' to ' + moment(end).format('LLLL')
  }
}

export function formatDate (date) {
  var dateObj = (typeof date === 'string' ? new Date(date) : date)
  return `${dateObj.toLocaleString('en-us', { month: 'long' })} ${dateObj.getDate()}, ${dateObj.getFullYear()}`
}

marked.setOptions({
  gfm: true,
  breaks: true,
  sanitize: true
})

export const markdown = marked
<commit_msg>fix rendering bug with recent posts<commit_after>import sanitizeHtml from 'sanitize-html'
import prettyDate from 'pretty-date'
import truncate from 'html-truncate'
import linkify from './linkify'
import moment from 'moment-timezone'
import marked from 'marked'

export function sanitize (text) {
  if (!text) return ''

  // remove leading   (a side-effect of contenteditable)
  var strippedText = text.replace(/
 /gi, '
')

  return sanitizeHtml(strippedText, {
    allowedTags: ['a', 'p', 'br', 'ul', 'ol', 'li', 'strong', 'em'],
    allowedAttributes: {
      'a': ['href', 'data-user-id']
    },

    // remove empty paragraphs
    exclusiveFilter: function (frame) {
      return frame.tag === 'p' && !frame.text.trim()
    }
  })
}

export function present (text, opts) {
  if (!text) return '

'

  // wrap in a
 tag
  if (text.substring(0, 3) !== '
') text = `<p>${text}</p>`

  // make links and hashtags
  text = linkify(text)

  if (opts && opts.maxlength) text = truncate(text, opts.maxlength)

  return text
}

export function humanDate (date, short) {
  var ret = prettyDate.format(typeof date === 'string' ? new Date(date) : date)
  if (short) {
    ret = ret.replace(' ago', '')
  } else {
    // this workaround prevents a "React attempted to use reuse markup" error
    // which happens if the timestamp is less than 1 minute ago, because the
    // server renders "N seconds ago", but by the time React is loaded on the
    // client side, it's "N+1 seconds ago"
    let match = ret.match(/(\d+) seconds? ago/)
    if (match) {
      if (Number(match[1]) >= 50) return '1 minute ago'
      return 'just now'
    }
  }
  return ret
}

const sameDay = (t1, t2) =>
  t1.getFullYear() === t2.getFullYear() &&
  t1.getMonth() === t2.getMonth() &&
  t1.getDate() === t2.getDate()

export function timeRange (start, end) {
  let startText = moment(start).calendar(null, {
    sameElse: 'dddd, MMM D, YYYY [at] h:mm A'
  })
  if (!end) {
    return startText
  } else if (sameDay(start, end)) {
    startText = startText.replace(' at ', ' from ')
    let endText = moment(end).format('h:mm A')
    return `${startText} to ${endText}`
  } else {
    return `${startText} to ${moment(end).calendar()}`
  }
}

export function timeRangeFull (start, end) {
  if (!end) {
    return moment(start).format('LLLL')
  } else {
    return moment(start).format('LLLL') + ' to ' + moment(end).format('LLLL')
  }
}

export function formatDate (date) {
  var dateObj = (typeof date === 'string' ? new Date(date) : date)
  return `${dateObj.toLocaleString('en-us', { month: 'long' })} ${dateObj.getDate()}, ${dateObj.getFullYear()}`
}

marked.setOptions({
  gfm: true,
  breaks: true,
  sanitize: true
})

export const markdown = marked
<|endoftext|>


<commit_before>import React from 'react';
import Relay from 'react-relay';
import throttle from 'throttleit';
import { seconds } from 'metrick/duration';

import Spinner from '../../shared/Spinner';
import Panel from '../../shared/Panel';
import Button from '../../shared/Button';
import Icon from '../../shared/Icon';
import PageWithContainer from '../../shared/PageWithContainer';

import JobRow from './job-row';
import StateSelector from './state-selector';

const PAGE_SIZE = 100;

class AgentIndex extends React.Component {
  static propTypes = {
    organization: React.PropTypes.object.isRequired
  };

  state = {
    loadingMore: false,
    switchingStates: false,
    selectedJobState: null
  };

  componentDidMount() {
    this.props.relay.forceFetch({ isMounted: true }, (readyState) => {
      // if (readyState.done) {
      //   this.startTimeout();
      // }
    });
  }

  render() {
    return (
      <PageWithContainer>
        <Panel>
          <Panel.Header>Job Explorer</Panel.Header>
          <Panel.Section>

                  {this.renderSearchIcon()}

                <input type="text" className="input" placeholder="Search by agent query rules…" style={{ paddingLeft: 28 }} onKeyUp={this.handleAgentQueryRuleSearch} />

States:
 <StateSelector selection={this.state.selectedJobState} onSelect={this.handleStateSelection} />

          </Panel.Section>
          {this.renderJobsList()}
          {this.renderFooter()}
        </Panel>
      </PageWithContainer>
    );
  }

  renderSearchIcon() {
    if (this.state.searching) {
      return (
        <Spinner size={15} color={false}/>
      );
    } else {
      return (
        <Icon icon="search" className="gray" style={{ width: 15, height: 15 }} />
      );
    }
  }

  renderFooter() {
    if(!this.props.organization.jobs || !this.props.organization.jobs.pageInfo.hasNextPage || this.state.switchingStates) {
      return null;
    }

    if(this.state.loadingMore) {
      return (
        <Panel.Footer className="center">
          <Spinner style={{ margin: 8 }} />
        </Panel.Footer>
      );
    } else {
      return (
        <Panel.Footer className="center">
          <Button outline={true} theme="default" onClick={this.handleLoadMoreClick}>Load more…</Button>
        </Panel.Footer>
      )
    }
  }

  renderJobsList() {
    const jobs = this.props.organization.jobs;

    if(!jobs || this.state.switchingStates) {
      return (
        <Panel.Section className="center">
          <Spinner />
        </Panel.Section>
      )
    } else {
      if (jobs.edges.length == 0) {
        return (
          <Panel.Section className="center">

No jobs here!

          </Panel.Section>
        )
      } else {
        return jobs.edges.map((edge) => {
          return (
            <JobRow key={edge.node.id} job={edge.node} />
          );
        });
      }
    }
  }

  handleAgentQueryRuleSearch = (event) => {
    const agentQueryRules = event.target.value == "" ? null : event.target.value.split(" ");

    clearTimeout(this._timeout);

    this._timeout = setTimeout(() => {
      delete this._timeout;

      this.setState({ searching: true });

      this.props.relay.forceFetch({ agentQueryRules: agentQueryRules }, (readyState) => {
        if (readyState.done) {
          this.setState({ searching: false });
        }
      });
    }, 1::seconds);
  };

  handleStateSelection = (state) => {
    this.setState({ switchingStates: true, selectedJobState: state });

    // Dunno why state comes through as `null`
    const newState = state == "null" ? null : state;

    this.props.relay.forceFetch({ state: newState, pageSize: PAGE_SIZE }, (readyState) => {
      if (readyState.done) {
        this.setState({ switchingStates: false });
      }
    });
  };

  handleLoadMoreClick = () => {
    this.setState({ loadingMore: true });

    const newPageSize = this.props.relay.variables.pageSize + PAGE_SIZE;

    this.props.relay.forceFetch({ pageSize: newPageSize }, (readyState) => {
      if (readyState.done) {
        this.setState({ loadingMore: false });
      }
    });
  };
}

export default Relay.createContainer(AgentIndex, {
  initialVariables: {
    isMounted: false,
    state: null,
    agentQueryRules: null,
    pageSize: PAGE_SIZE
  },

  fragments: {
    organization: () => Relay.QL`
      fragment on Organization {
        jobs(first: $pageSize, type: COMMAND, state: $state, agentQueryRules: $agentQueryRules) @include(if: $isMounted) {
          count
          edges {
            node {
              ...on JobTypeCommand {
                id
              }
              ${JobRow.getFragment('job')}
            }
          }
          pageInfo {
            hasNextPage
          }
        }
      }
    `
  }
});
<commit_msg>Added some basic count gear on the jobs explorer<commit_after>import React from 'react';
import Relay from 'react-relay';
import throttle from 'throttleit';
import { seconds } from 'metrick/duration';

import Spinner from '../../shared/Spinner';
import Panel from '../../shared/Panel';
import Button from '../../shared/Button';
import Icon from '../../shared/Icon';
import PageWithContainer from '../../shared/PageWithContainer';

import JobRow from './job-row';
import StateSelector from './state-selector';

const PAGE_SIZE = 100;

class AgentIndex extends React.Component {
  static propTypes = {
    organization: React.PropTypes.object.isRequired
  };

  state = {
    loadingMore: false,
    switchingStates: false,
    selectedJobState: null
  };

  componentDidMount() {
    this.props.relay.forceFetch({ isMounted: true });
  }

  render() {
    return (
      <PageWithContainer>
        <Panel>
          <Panel.Header>Job Explorer</Panel.Header>
          <Panel.Section>

                  {this.renderSearchIcon()}

                <input type="text" className="input" placeholder="Search by agent query rules…" style={{ paddingLeft: 28 }} onKeyUp={this.handleAgentQueryRuleSearch} />

States:
 <StateSelector selection={this.state.selectedJobState} onSelect={this.handleStateSelection} />

            {this.renderCounts()}
          </Panel.Section>
          {this.renderJobsList()}
          {this.renderFooter()}
        </Panel>
      </PageWithContainer>
    );
  }

  renderSearchIcon() {
    if (this.state.searching) {
      return (
        <Spinner size={15} color={false}/>
      );
    } else {
      return (
        <Icon icon="search" className="gray" style={{ width: 15, height: 15 }} />
      );
    }
  }

  renderCounts() {
    if(!this.state.switchingStates && this.props.organization.jobs && this.props.organization.jobs.count > 0) {
      return (

          Showing {this.props.organization.jobs.edges.length} of {this.props.organization.jobs.count}

      );
    }
  }

  renderFooter() {
    if(!this.props.organization.jobs || !this.props.organization.jobs.pageInfo.hasNextPage || this.state.switchingStates) {
      return null;
    }

    if(this.state.loadingMore) {
      return (
        <Panel.Footer className="center">
          <Spinner style={{ margin: 8 }} />
        </Panel.Footer>
      );
    } else {
      return (
        <Panel.Footer className="center">
          <Button outline={true} theme="default" onClick={this.handleLoadMoreClick}>Load more…</Button>
        </Panel.Footer>
      )
    }
  }

  renderJobsList() {
    const jobs = this.props.organization.jobs;

    if(!jobs || this.state.switchingStates) {
      return (
        <Panel.Section className="center">
          <Spinner />
        </Panel.Section>
      )
    } else {
      if (jobs.edges.length == 0) {
        return (
          <Panel.Section className="center">

No jobs here!

          </Panel.Section>
        )
      } else {
        return jobs.edges.map((edge) => {
          return (
            <JobRow key={edge.node.id} job={edge.node} />
          );
        });
      }
    }
  }

  handleAgentQueryRuleSearch = (event) => {
    const agentQueryRules = event.target.value == "" ? null : event.target.value.split(" ");

    clearTimeout(this._timeout);

    this._timeout = setTimeout(() => {
      delete this._timeout;

      this.setState({ searching: true });

      this.props.relay.forceFetch({ agentQueryRules: agentQueryRules }, (readyState) => {
        if (readyState.done) {
          this.setState({ searching: false });
        }
      });
    }, 1::seconds);
  };

  handleStateSelection = (state) => {
    this.setState({ switchingStates: true, selectedJobState: state });

    // Dunno why state comes through as `null`
    const newState = state == "null" ? null : state;

    this.props.relay.forceFetch({ state: newState, pageSize: PAGE_SIZE }, (readyState) => {
      if (readyState.done) {
        this.setState({ switchingStates: false });
      }
    });
  };

  handleLoadMoreClick = () => {
    this.setState({ loadingMore: true });

    const newPageSize = this.props.relay.variables.pageSize + PAGE_SIZE;

    this.props.relay.forceFetch({ pageSize: newPageSize }, (readyState) => {
      if (readyState.done) {
        this.setState({ loadingMore: false });
      }
    });
  };
}

export default Relay.createContainer(AgentIndex, {
  initialVariables: {
    isMounted: false,
    state: null,
    agentQueryRules: null,
    pageSize: PAGE_SIZE
  },

  fragments: {
    organization: () => Relay.QL`
      fragment on Organization {
        jobs(first: $pageSize, type: COMMAND, state: $state, agentQueryRules: $agentQueryRules) @include(if: $isMounted) {
          count
          edges {
            node {
              ...on JobTypeCommand {
                id
              }
              ${JobRow.getFragment('job')}
            }
          }
          pageInfo {
            hasNextPage
          }
        }
      }
    `
  }
});
<|endoftext|>


<commit_before>"use strict";

var filecache = require('filecache')
  , url = require('url')
  , regExp_AcceptEncoding = new RegExp('(gzip|deflate)', 'g')

module.exports = create

function create(options, fc) {
  if(!(options != null)) {
    options =
    { etag: true
    , lastmod: true
    , expires: 3600000 // milliseconds
    , maxAge: 3600     // seconds
    }
  }

  var cache = fc.cache

  function handleRequest(req, res, next) {
    var u = url.parse(req.url)
      , statusCode
      , contents
      , headers = {}

    // lookup the contents to serve
    if(u.pathname === '/' && cache['/index.html']) {
      u.pathname = '/index.html'
    }

    // handles file-not-found
    if(!cache[u.pathname]) {
      if(!cache['/404.html']) {
        if(next) {
          return next()
        }
        req.writeHead(404)
        req.end()
        return
      }
      statusCode = 404
      u.pathname = '/404.html'
    } else {
      statusCode = 200
    }

    // sets the content to serve
    contents = cache[u.pathname]
    headers['Content-Type'] = contents.mime_type

    // http cache
    if(options) {
      if(options.etag) {
        if(req.headers['if-none-match'] != null
            && req.headers['if-none-match'] === contents.hash) {
          res.writeHead(304)
          res.end()
          return next && next(false)
        }
        headers['ETag'] = contents.hash
      }

      if(options.lastmod) {
        if(req.headers['if-modified-since'] != null
            && new Date(req.headers['if-modified-since']).getTime() === contents.mtime.getTime()) {
          res.writeHead(304)
          res.end()
          return next && next(false)
        }
        headers['Last-Modified'] = contents.mtime.toUTCString()
      }

      if(options.expires) {
        headers['Expires'] = new Date(contents.mtime + (options.expires*1000)).toUTCString()
      }

      if(options.maxAge) {
        headers['Max-Age'] = options.maxAge
      }

      headers['Cache-Control'] = 'public'
    }

    // http encoding
    if((contents.gzip || contents.deflate) && req.headers['accept-encoding']) {
      var ae = req.headers['accept-encoding'].match(regExp_AcceptEncoding)

      if(contents.gzip
          && ae.indexOf('gzip') !== -1
          && contents.gzip.length < contents.length) {
        contents = contents.gzip
        headers['Content-Encoding'] = 'gzip'
      } else
      if(contents.deflate
          && ae.indexOf('deflate') !== -1
          && contents.deflate.length < contents.length) {
        contents = contents.deflate
        headers['Content-Encoding'] = 'deflate'
      }
    }

    // sends the contents
    headers['Content-Length'] = contents.length
    res.writeHead(statusCode, headers)
    res.end(contents)

    next && next(false)
  }

  return handleRequest
}
<commit_msg>Added options.handler<commit_after>"use strict";

var filecache = require('filecache')
  , url = require('url')
  , regExp_AcceptEncoding = new RegExp('(gzip|deflate)', 'g')

module.exports = create

function create(options, fc) {
  if(!(options != null)) {
    options =
    { etag: true
    , lastmod: true
    , expires: 3600000 // milliseconds
    , maxAge: 3600     // seconds
    }
  }

  var cache = fc.cache

  function handleRequest(req, res, next) {
    var u = url.parse(req.url)
      , statusCode
      , contents
      , headers = {}

    req.urlparts = u

    // lookup the contents to serve
    if(u.pathname === '/' && cache['/index.html']) {
      u.pathname = '/index.html'
    }

    // handles file-not-found
    if(!cache[u.pathname]) {
      if(!cache['/404.html']) {
        // user-defined handler
        if(options.handler) {
          return options.handler(req, res, next)
        }

        if(next) {
          return next()
        }

        req.writeHead(404)
        req.end()
        return
      }
      statusCode = 404
      u.pathname = '/404.html'
    } else {
      statusCode = 200
    }

    // sets the content to serve
    contents = cache[u.pathname]
    headers['Content-Type'] = contents.mime_type

    // http cache
    if(options) {
      if(options.etag) {
        if(req.headers['if-none-match'] != null
            && req.headers['if-none-match'] === contents.hash) {
          res.writeHead(304)
          res.end()
          return next && next(false)
        }
        headers['ETag'] = contents.hash
      }

      if(options.lastmod) {
        if(req.headers['if-modified-since'] != null
            && new Date(req.headers['if-modified-since']).getTime() === contents.mtime.getTime()) {
          res.writeHead(304)
          res.end()
          return next && next(false)
        }
        headers['Last-Modified'] = contents.mtime.toUTCString()
      }

      if(options.expires) {
        headers['Expires'] = new Date(contents.mtime + (options.expires*1000)).toUTCString()
      }

      if(options.maxAge) {
        headers['Max-Age'] = options.maxAge
      }

      headers['Cache-Control'] = 'public'
    }

    // http encoding
    if((contents.gzip || contents.deflate) && req.headers['accept-encoding']) {
      var ae = req.headers['accept-encoding'].match(regExp_AcceptEncoding)

      if(contents.gzip
          && ae.indexOf('gzip') !== -1
          && contents.gzip.length < contents.length) {
        contents = contents.gzip
        headers['Content-Encoding'] = 'gzip'
      } else
      if(contents.deflate
          && ae.indexOf('deflate') !== -1
          && contents.deflate.length < contents.length) {
        contents = contents.deflate
        headers['Content-Encoding'] = 'deflate'
      }
    }

    // sends the contents
    headers['Content-Length'] = contents.length
    res.writeHead(statusCode, headers)
    res.end(contents)

    next && next(false)
  }

  return handleRequest
}
<|endoftext|>


<commit_before>import {Observable as O} from 'rx';
import BitSet from 'bitset.js';

import {parseDataAttr} from '../../../lib/utils';

import {helpAction} from './help';
import {settingsAction} from './settings';
import {openAction} from './open';
import {saveAction} from './save';

const touchTarget = (evt) =>
  document.elementFromPoint(
    evt.changedTouches[0].clientX,
    evt.changedTouches[0].clientY
  )
;
export default (DOM, keydown) => {
  const cancel$ = keydown
    .filter((evt) => evt.keyCode === 27)
  ;

  const touchEnd$ = O.fromEvent(document, 'touchend');
  const mouseUp$ = O.fromEvent(document, 'mouseup');

  const mouseEnterEvent$ = DOM
    .select('.kv-cell-atom[data-edit="loops"][data-kv-cell]')
    .events('mouseenter', true);

  const touchMoveEvent$ = DOM
    .select('.kv-cell-atom[data-edit="loops"][data-kv-cell]')
    .events('touchmove');

  const pointerEnter$ = O.merge(
    mouseEnterEvent$
      .map((evt) => ({
        cell: BitSet(evt.currentTarget.dataset.kvCell),
      }))
    ,
    touchMoveEvent$
      .map((evt) => {
        const element = touchTarget(evt);
        return {
          cell: element && element.dataset.hasOwnProperty('kvCell') ?
            BitSet(element.dataset.kvCell) : null,
        };
      })
  );

  const pointerDownEvent$ = O.merge(
      DOM
        .select('.kv-cell-atom[data-edit="loops"][data-kv-cell]')
        .events('touchstart'),
      DOM
        .select('.kv-cell-atom[data-edit="loops"][data-kv-cell]')
        .events('mousedown')
    );

  const pointerDown$ = pointerDownEvent$
    .map((evt) => ({
      cell: BitSet(evt.currentTarget.dataset.kvCell),
      output: parseInt(evt.currentTarget.dataset.kvOutput, 10),
    }))
    .filter(({cell}) => cell !== null)
    ;

  const pointerUp$ = O.merge(
    touchEnd$,
    mouseUp$
  );

  const drag$ = pointerDown$
    .map(({cell, output}) =>
      O.just({
        output: output,
        startCell: cell,
        targetCell: cell,
      }).concat(
        pointerEnter$
        .filter(({cell: c}) => c !== null)
        .distinctUntilChanged(
          ({cell: c}) => c,
          (a, b) => a.equals(b)
        )
        .map(({cell: targetCell}) => ({
          output,
          startCell: cell,
          targetCell,
        })
      )
      ).takeUntil(
        cancel$
      ).takeUntil(
        pointerUp$
      )
    )
    .switch();

  const dragEnd$ = drag$
    .sample(
      O.merge(
        pointerDown$.map(() => pointerUp$),
        cancel$.map(() => O.empty())
      ).switch()
    );

  const help = helpAction({DOM});
  const open = openAction({DOM});
  const exprt = saveAction({DOM});
  const settings = settingsAction({DOM});

  const removeLoopButton = DOM
    .select('[data-loop-index]');

  const removeLoopEvent$ = removeLoopButton
    .events('click');

  const addOutputButton = DOM
    .select('[data-kv-add-output]');

  const addOutputEvent$ = addOutputButton
    .events('click');

  const removeOutputEvent$ = DOM
    .select('[data-kv-remove-output]')
    .events('click');

  const outputItem = DOM
    .select('[data-kv-output]');

  const outputLabel = DOM
    .select('.state-editable[data-kv-output-label]');

  const outputEditLabel = DOM
    .select('[data-kv-output-edit-label]');

  const selectOutputEvent$ = outputItem
    .events('click')
    .filter((e) => e.target.tagName !== 'INPUT');

  const editModeButton = DOM
    .select('[data-edit-mode]');

  const kvModeButton = DOM
    .select('[data-kv-mode]');

  const switchKvModeEvent$ = kvModeButton
    .events('click');

  const switchEditModeEvent$ = editModeButton
    .events('click');

  const incrementButton = DOM
    .select('[data-kv-counter="increment"]');

  const decrementButton = DOM
    .select('[data-kv-counter="decrement"]');

  const incrementEvent$ = incrementButton
    .events('click');

  const decrementEvent$ = decrementButton
    .events('click');

  const startRenameEvent$ = outputLabel
    .events('click')
    .filter((evt) => evt.target.tagName !== 'INPUT');

  const cancelRenameEvent$ = O.merge(
    outputEditLabel
        .events('keydown')
        .filter((e) => e.keyCode === 27),
    outputEditLabel
        .events('focusout')
  );

  const tryOutputNameEvent$ = outputEditLabel
    .events('input');

  const confirmOutputNameEvent$ = outputEditLabel
    .events('keydown')
    .filter((e) => e.keyCode === 13);

  return {
    addInput$:
      incrementEvent$
        .map(() => true)
        .share(),
    removeInput$:
      decrementEvent$
        .map(() => true)
        .share(),
    cycleValue$:
      DOM
        .select('.kv-cell-atom[data-edit="function"][data-kv-cell]')
        .events('click')
        .map((evt) => ({
          reverse: evt.altKey,
          output: parseInt(evt.currentTarget.dataset.kvOutput, 10),
          cell: BitSet(evt.currentTarget.dataset.kvCell),
        }))
        .share(),
    removeLoop$:
      removeLoopEvent$
        .map(parseDataAttr('loopIndex'))
        .filter(isFinite)
        .share(),
    tryLoop$:
      drag$
        .share(),
    stopTryLoop$:
      O.merge(dragEnd$, cancel$)
        .map(() => true)
        .share(),
    addLoop$:
      dragEnd$.share(),
    addOutput$:
      addOutputEvent$
        .map(() => true)
        .share(),
    removeOutput$:
      removeOutputEvent$
        .map(parseDataAttr('kvRemoveOutput'))
        .filter(isFinite)
        .share(),
    selectOutput$:
      selectOutputEvent$
        .map(parseDataAttr('kvOutput'))
        .filter(isFinite)
        .share(),
    switchKvMode$:
      switchKvModeEvent$
        .map((evt) => evt.currentTarget.dataset.kvMode)
        .share(),
    switchEditMode$:
      switchEditModeEvent$
        .map((evt) => evt.currentTarget.dataset.editMode)
        .share(),
    help$: help.action$,
    settings$: settings.action$,
    open$: open.action$,
    save$: exprt.action$,

    startRename$:
      startRenameEvent$
        .map((evt) => parseInt(evt.currentTarget.dataset.kvOutputLabel, 10))
        .share(),

    cancelRename$:
      cancelRenameEvent$
        .map(() => true)
        .share(),

    tryOutputName$:
      tryOutputNameEvent$
        .map((evt) => ({
          outputIndex: parseInt(
            evt.currentTarget.dataset.kvOutputEditLabel,
            10),
          name: evt.currentTarget.value,
        }))
        .share(),

    confirmOutputName$:
      confirmOutputNameEvent$
        .map(() => true)
        .share(),

    preventDefault: O.merge(
      help.preventDefault,
      settings.preventDefault,
      open.preventDefault,
      mouseEnterEvent$,
      touchMoveEvent$,
      pointerDownEvent$,
      removeLoopEvent$,
      removeLoopButton.events('mousedown'),
      addOutputEvent$,
      addOutputButton.events('mousedown'),
      removeOutputEvent$,
      selectOutputEvent$,
      outputItem.events('mousedown')
        .filter((e) => e.target.tagName !== 'INPUT'),
      switchKvModeEvent$,
      kvModeButton.events('mousedown'),
      switchEditModeEvent$,
      editModeButton.events('mousedown'),
      incrementEvent$,
      decrementEvent$,
      incrementButton.events('mousedown'),
      decrementButton.events('mousedown'),
      startRenameEvent$,
      cancelRenameEvent$,
      tryOutputNameEvent$,
      confirmOutputNameEvent$
    ).share(),
  };
};
<commit_msg>supress save button focus<commit_after>import {Observable as O} from 'rx';
import BitSet from 'bitset.js';

import {parseDataAttr} from '../../../lib/utils';

import {helpAction} from './help';
import {settingsAction} from './settings';
import {openAction} from './open';
import {saveAction} from './save';

const touchTarget = (evt) =>
  document.elementFromPoint(
    evt.changedTouches[0].clientX,
    evt.changedTouches[0].clientY
  )
;
export default (DOM, keydown) => {
  const cancel$ = keydown
    .filter((evt) => evt.keyCode === 27)
  ;

  const touchEnd$ = O.fromEvent(document, 'touchend');
  const mouseUp$ = O.fromEvent(document, 'mouseup');

  const mouseEnterEvent$ = DOM
    .select('.kv-cell-atom[data-edit="loops"][data-kv-cell]')
    .events('mouseenter', true);

  const touchMoveEvent$ = DOM
    .select('.kv-cell-atom[data-edit="loops"][data-kv-cell]')
    .events('touchmove');

  const pointerEnter$ = O.merge(
    mouseEnterEvent$
      .map((evt) => ({
        cell: BitSet(evt.currentTarget.dataset.kvCell),
      }))
    ,
    touchMoveEvent$
      .map((evt) => {
        const element = touchTarget(evt);
        return {
          cell: element && element.dataset.hasOwnProperty('kvCell') ?
            BitSet(element.dataset.kvCell) : null,
        };
      })
  );

  const pointerDownEvent$ = O.merge(
      DOM
        .select('.kv-cell-atom[data-edit="loops"][data-kv-cell]')
        .events('touchstart'),
      DOM
        .select('.kv-cell-atom[data-edit="loops"][data-kv-cell]')
        .events('mousedown')
    );

  const pointerDown$ = pointerDownEvent$
    .map((evt) => ({
      cell: BitSet(evt.currentTarget.dataset.kvCell),
      output: parseInt(evt.currentTarget.dataset.kvOutput, 10),
    }))
    .filter(({cell}) => cell !== null)
    ;

  const pointerUp$ = O.merge(
    touchEnd$,
    mouseUp$
  );

  const drag$ = pointerDown$
    .map(({cell, output}) =>
      O.just({
        output: output,
        startCell: cell,
        targetCell: cell,
      }).concat(
        pointerEnter$
        .filter(({cell: c}) => c !== null)
        .distinctUntilChanged(
          ({cell: c}) => c,
          (a, b) => a.equals(b)
        )
        .map(({cell: targetCell}) => ({
          output,
          startCell: cell,
          targetCell,
        })
      )
      ).takeUntil(
        cancel$
      ).takeUntil(
        pointerUp$
      )
    )
    .switch();

  const dragEnd$ = drag$
    .sample(
      O.merge(
        pointerDown$.map(() => pointerUp$),
        cancel$.map(() => O.empty())
      ).switch()
    );

  const help = helpAction({DOM});
  const open = openAction({DOM});
  const save = saveAction({DOM});
  const settings = settingsAction({DOM});

  const removeLoopButton = DOM
    .select('[data-loop-index]');

  const removeLoopEvent$ = removeLoopButton
    .events('click');

  const addOutputButton = DOM
    .select('[data-kv-add-output]');

  const addOutputEvent$ = addOutputButton
    .events('click');

  const removeOutputEvent$ = DOM
    .select('[data-kv-remove-output]')
    .events('click');

  const outputItem = DOM
    .select('[data-kv-output]');

  const outputLabel = DOM
    .select('.state-editable[data-kv-output-label]');

  const outputEditLabel = DOM
    .select('[data-kv-output-edit-label]');

  const selectOutputEvent$ = outputItem
    .events('click')
    .filter((e) => e.target.tagName !== 'INPUT');

  const editModeButton = DOM
    .select('[data-edit-mode]');

  const kvModeButton = DOM
    .select('[data-kv-mode]');

  const switchKvModeEvent$ = kvModeButton
    .events('click');

  const switchEditModeEvent$ = editModeButton
    .events('click');

  const incrementButton = DOM
    .select('[data-kv-counter="increment"]');

  const decrementButton = DOM
    .select('[data-kv-counter="decrement"]');

  const incrementEvent$ = incrementButton
    .events('click');

  const decrementEvent$ = decrementButton
    .events('click');

  const startRenameEvent$ = outputLabel
    .events('click')
    .filter((evt) => evt.target.tagName !== 'INPUT');

  const cancelRenameEvent$ = O.merge(
    outputEditLabel
        .events('keydown')
        .filter((e) => e.keyCode === 27),
    outputEditLabel
        .events('focusout')
  );

  const tryOutputNameEvent$ = outputEditLabel
    .events('input');

  const confirmOutputNameEvent$ = outputEditLabel
    .events('keydown')
    .filter((e) => e.keyCode === 13);

  return {
    addInput$:
      incrementEvent$
        .map(() => true)
        .share(),
    removeInput$:
      decrementEvent$
        .map(() => true)
        .share(),
    cycleValue$:
      DOM
        .select('.kv-cell-atom[data-edit="function"][data-kv-cell]')
        .events('click')
        .map((evt) => ({
          reverse: evt.altKey,
          output: parseInt(evt.currentTarget.dataset.kvOutput, 10),
          cell: BitSet(evt.currentTarget.dataset.kvCell),
        }))
        .share(),
    removeLoop$:
      removeLoopEvent$
        .map(parseDataAttr('loopIndex'))
        .filter(isFinite)
        .share(),
    tryLoop$:
      drag$
        .share(),
    stopTryLoop$:
      O.merge(dragEnd$, cancel$)
        .map(() => true)
        .share(),
    addLoop$:
      dragEnd$.share(),
    addOutput$:
      addOutputEvent$
        .map(() => true)
        .share(),
    removeOutput$:
      removeOutputEvent$
        .map(parseDataAttr('kvRemoveOutput'))
        .filter(isFinite)
        .share(),
    selectOutput$:
      selectOutputEvent$
        .map(parseDataAttr('kvOutput'))
        .filter(isFinite)
        .share(),
    switchKvMode$:
      switchKvModeEvent$
        .map((evt) => evt.currentTarget.dataset.kvMode)
        .share(),
    switchEditMode$:
      switchEditModeEvent$
        .map((evt) => evt.currentTarget.dataset.editMode)
        .share(),
    help$: help.action$,
    settings$: settings.action$,
    open$: open.action$,
    save$: save.action$,

    startRename$:
      startRenameEvent$
        .map((evt) => parseInt(evt.currentTarget.dataset.kvOutputLabel, 10))
        .share(),

    cancelRename$:
      cancelRenameEvent$
        .map(() => true)
        .share(),

    tryOutputName$:
      tryOutputNameEvent$
        .map((evt) => ({
          outputIndex: parseInt(
            evt.currentTarget.dataset.kvOutputEditLabel,
            10),
          name: evt.currentTarget.value,
        }))
        .share(),

    confirmOutputName$:
      confirmOutputNameEvent$
        .map(() => true)
        .share(),

    preventDefault: O.merge(
      help.preventDefault,
      settings.preventDefault,
      open.preventDefault,
      save.preventDefault,
      mouseEnterEvent$,
      touchMoveEvent$,
      pointerDownEvent$,
      removeLoopEvent$,
      removeLoopButton.events('mousedown'),
      addOutputEvent$,
      addOutputButton.events('mousedown'),
      removeOutputEvent$,
      selectOutputEvent$,
      outputItem.events('mousedown')
        .filter((e) => e.target.tagName !== 'INPUT'),
      switchKvModeEvent$,
      kvModeButton.events('mousedown'),
      switchEditModeEvent$,
      editModeButton.events('mousedown'),
      incrementEvent$,
      decrementEvent$,
      incrementButton.events('mousedown'),
      decrementButton.events('mousedown'),
      startRenameEvent$,
      cancelRenameEvent$,
      tryOutputNameEvent$,
      confirmOutputNameEvent$
    ).share(),
  };
};
<|endoftext|>


<commit_before>export function isGet(request) {
  return request.method === 'GET';
}

export function isPost(request) {
  return request.method === 'POST';
}

export function isPath(request) {
  return request.path === '/graphql';
}

export function required() {
  throw new Error('Required option is missing');
}

const GRAPHIQL_VERSION = '0.7.1';

export function renderGraphiQL({ query, variables, version = GRAPHIQL_VERSION } = {}) {
  return `
    <!DOCTYPE html>
    <html>
      <head>
        <style>
           html, body {
             height: 100%;
             margin: 0;
             width: 100%;
             overflow: hidden;
           }
         </style>
          <link href="//cdn.jsdelivr.net/graphiql/${version}/graphiql.css" rel="stylesheet" />
          <script src="//cdn.jsdelivr.net/fetch/0.9.0/fetch.min.js"></script>
          <script src="//cdn.jsdelivr.net/react/0.14.7/react.min.js"></script>
          <script src="//cdn.jsdelivr.net/react/0.14.7/react-dom.min.js"></script>>
          <script src="//cdn.jsdelivr.net/graphiql/${version}/graphiql.min.js"></script>
      </head>
      <body>
        Loading...
        <script>
          /**
           * This GraphiQL example illustrates how to use some of GraphiQL's props
           * in order to enable reading and updating the URL parameters, making
           * link sharing of queries a little bit easier.
           *
           * This is only one example of this kind of feature, GraphiQL exposes
           * various React params to enable interesting integrations.
           */
          // Parse the search string to get url parameters.
          var search = window.location.search;
          var parameters = {};
          search.substr(1).split('&').forEach(function (entry) {
            var eq = entry.indexOf('=');
            if (eq >= 0) {
              parameters[decodeURIComponent(entry.slice(0, eq))] =
                decodeURIComponent(entry.slice(eq + 1));
            }
          });
          // if variables was provided, try to format it.
          if (parameters.variables) {
            try {
              parameters.variables =
                JSON.stringify(JSON.parse(parameters.variables), null, 2);
            } catch (e) {
              // Do nothing, we want to display the invalid JSON as a string, rather
              // than present an error.
            }
          }
          // When the query and variables string is edited, update the URL bar so
          // that it can be easily shared
          function onEditQuery(newQuery) {
            parameters.query = newQuery;
            updateURL();
          }
          function onEditVariables(newVariables) {
            parameters.variables = newVariables;
            updateURL();
          }
          function updateURL() {
            var newSearch = '?' + Object.keys(parameters).map(function (key) {
              return encodeURIComponent(key) + '=' +
                encodeURIComponent(parameters[key]);
            }).join('&');
            history.replaceState(null, null, newSearch);
          }
          // Defines a GraphQL fetcher using the fetch API.
          function graphQLFetcher(graphQLParams) {
            return fetch(window.location.origin + '/graphql', {
              method: 'post',
              headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
              },
              body: JSON.stringify(graphQLParams),
              credentials: 'include',
            }).then(function (response) {
              return response.text();
            }).then(function (responseBody) {
              try {
                return JSON.parse(responseBody);
              } catch (error) {
                return responseBody;
              }
            });
          }
          // Render <GraphiQL /> into the body.
          ReactDOM.render(
            React.createElement(GraphiQL, {
              fetcher: graphQLFetcher,
              query: ${query ? `\`${query}\`` : 'parameters.query'},
              variables: ${variables ? `\`${variables}\`` : 'parameters.variables'},
              onEditQuery: onEditQuery,
              onEditVariables: onEditVariables
            }),
            document.body
          );
        </script>
      </body>
    </html>`;
}
<commit_msg>feat(util): use relative url instead of hardcoded (#40)<commit_after>export function isGet(request) {
  return request.method === 'GET';
}

export function isPost(request) {
  return request.method === 'POST';
}

export function isPath(request) {
  return request.path === '/graphql';
}

export function required() {
  throw new Error('Required option is missing');
}

const GRAPHIQL_VERSION = '0.7.1';

export function renderGraphiQL({ query, variables, version = GRAPHIQL_VERSION } = {}) {
  return `
    <!DOCTYPE html>
    <html>
      <head>
        <style>
           html, body {
             height: 100%;
             margin: 0;
             width: 100%;
             overflow: hidden;
           }
         </style>
          <link href="//cdn.jsdelivr.net/graphiql/${version}/graphiql.css" rel="stylesheet" />
          <script src="//cdn.jsdelivr.net/fetch/0.9.0/fetch.min.js"></script>
          <script src="//cdn.jsdelivr.net/react/0.14.7/react.min.js"></script>
          <script src="//cdn.jsdelivr.net/react/0.14.7/react-dom.min.js"></script>>
          <script src="//cdn.jsdelivr.net/graphiql/${version}/graphiql.min.js"></script>
      </head>
      <body>
        Loading...
        <script>
          /**
           * This GraphiQL example illustrates how to use some of GraphiQL's props
           * in order to enable reading and updating the URL parameters, making
           * link sharing of queries a little bit easier.
           *
           * This is only one example of this kind of feature, GraphiQL exposes
           * various React params to enable interesting integrations.
           */
          // Parse the search string to get url parameters.
          var search = window.location.search;
          var parameters = {};
          search.substr(1).split('&').forEach(function (entry) {
            var eq = entry.indexOf('=');
            if (eq >= 0) {
              parameters[decodeURIComponent(entry.slice(0, eq))] =
                decodeURIComponent(entry.slice(eq + 1));
            }
          });
          // if variables was provided, try to format it.
          if (parameters.variables) {
            try {
              parameters.variables =
                JSON.stringify(JSON.parse(parameters.variables), null, 2);
            } catch (e) {
              // Do nothing, we want to display the invalid JSON as a string, rather
              // than present an error.
            }
          }
          // When the query and variables string is edited, update the URL bar so
          // that it can be easily shared
          function onEditQuery(newQuery) {
            parameters.query = newQuery;
            updateURL();
          }
          function onEditVariables(newVariables) {
            parameters.variables = newVariables;
            updateURL();
          }
          function updateURL() {
            var newSearch = '?' + Object.keys(parameters).map(function (key) {
              return encodeURIComponent(key) + '=' +
                encodeURIComponent(parameters[key]);
            }).join('&');
            history.replaceState(null, null, newSearch);
          }
          // Defines a GraphQL fetcher using the fetch API.
          function graphQLFetcher(graphQLParams) {
            return fetch(window.location.href, {
              method: 'post',
              headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json',
              },
              body: JSON.stringify(graphQLParams),
              credentials: 'include',
            }).then(function (response) {
              return response.text();
            }).then(function (responseBody) {
              try {
                return JSON.parse(responseBody);
              } catch (error) {
                return responseBody;
              }
            });
          }
          // Render <GraphiQL /> into the body.
          ReactDOM.render(
            React.createElement(GraphiQL, {
              fetcher: graphQLFetcher,
              query: ${query ? `\`${query}\`` : 'parameters.query'},
              variables: ${variables ? `\`${variables}\`` : 'parameters.variables'},
              onEditQuery: onEditQuery,
              onEditVariables: onEditVariables
            }),
            document.body
          );
        </script>
      </body>
    </html>`;
}
<|endoftext|>


<commit_before>'use strict';

var RingBuffer = require('ringbufferjs');

module.exports = NullStatsd;

function NullStatsd(capacity) {
    if (!(this instanceof NullStatsd)) {
        return new NullStatsd(capacity);
    }

    this._buffer = new RingBuffer(capacity || 50);
}

function NullStatsdRecord(type, name, value, delta, time) {
    this.type = type;
    this.name = name;
    this.value = value || null;
    this.delta = delta || null;
    this.time = time || null;
}

var proto = NullStatsd.prototype;

proto._write = function _write(record) {
    this._buffer.enq(record);
};

proto.gauge = function gauge(name, value) {
    this._write(new NullStatsdRecord('g', name, value));
};

proto.counter = function counter(name, value) {
    this._write(new NullStatsdRecord('c', name, null, value));
};

proto.increment = function increment(name, delta) {
    this._write(new NullStatsdRecord(
        'c',
        name,
        null,
        delta || 1
    ));
};

proto.decrement = function decrement(name, delta) {
    this._write(new NullStatsdRecord(
        'c',
        name,
        null,
        (-1 * Math.abs(delta || 1))
    ));
};

proto.timing = function timing(name, time) {
    this._write(new NullStatsdRecord(
        'ms',
        name,
        null,
        null,
        time
    ));
};

proto.close = function close() {
    for (var i = 0, len = this._buffer.size(); i < len; i++) {
        this._buffer.deq();
    }
};

proto.immediateGauge = function (name, value, cb) {
    this._write(new NullStatsdRecord(
        'g',
        name,
        value
    ));
    process.nextTick(cb);
};

proto.immediateIncrement = function (name, delta, cb) {
    this._write(new NullStatsdRecord(
        'c',
        name,
        null,
        delta || 1
    ));
    process.nextTick(cb);
};

proto.immediateDecrement = function (name, delta, cb) {
    this._write(new NullStatsdRecord(
        'c',
        name,
        null,
        (-1 * Math.abs(delta || 1))
    ));
    process.nextTick(cb);
};

proto.immediateCounter = function (name, value, cb) {
    this._write(new NullStatsdRecord(
        'c',
        name,
        null,
        value
    ));
    process.nextTick(cb);
};

proto.immediateTiming = function (name, time, cb) {
    this._write(new NullStatsdRecord(
        'ms',
        name,
        null,
        null,
        time
    ));
    process.nextTick(cb);
};

<commit_msg>Add dummy getChildClient method to NullStatsd<commit_after>'use strict';

var RingBuffer = require('ringbufferjs');

module.exports = NullStatsd;

function NullStatsd(capacity) {
    if (!(this instanceof NullStatsd)) {
        return new NullStatsd(capacity);
    }

    this._buffer = new RingBuffer(capacity || 50);
}

function NullStatsdRecord(type, name, value, delta, time) {
    this.type = type;
    this.name = name;
    this.value = value || null;
    this.delta = delta || null;
    this.time = time || null;
}

var proto = NullStatsd.prototype;

proto._write = function _write(record) {
    this._buffer.enq(record);
};

proto.gauge = function gauge(name, value) {
    this._write(new NullStatsdRecord('g', name, value));
};

proto.counter = function counter(name, value) {
    this._write(new NullStatsdRecord('c', name, null, value));
};

proto.increment = function increment(name, delta) {
    this._write(new NullStatsdRecord(
        'c',
        name,
        null,
        delta || 1
    ));
};

proto.decrement = function decrement(name, delta) {
    this._write(new NullStatsdRecord(
        'c',
        name,
        null,
        (-1 * Math.abs(delta || 1))
    ));
};

proto.timing = function timing(name, time) {
    this._write(new NullStatsdRecord(
        'ms',
        name,
        null,
        null,
        time
    ));
};

proto.close = function close() {
    for (var i = 0, len = this._buffer.size(); i < len; i++) {
        this._buffer.deq();
    }
};

proto.immediateGauge = function (name, value, cb) {
    this._write(new NullStatsdRecord(
        'g',
        name,
        value
    ));
    process.nextTick(cb);
};

proto.immediateIncrement = function (name, delta, cb) {
    this._write(new NullStatsdRecord(
        'c',
        name,
        null,
        delta || 1
    ));
    process.nextTick(cb);
};

proto.immediateDecrement = function (name, delta, cb) {
    this._write(new NullStatsdRecord(
        'c',
        name,
        null,
        (-1 * Math.abs(delta || 1))
    ));
    process.nextTick(cb);
};

proto.immediateCounter = function (name, value, cb) {
    this._write(new NullStatsdRecord(
        'c',
        name,
        null,
        value
    ));
    process.nextTick(cb);
};

proto.immediateTiming = function (name, time, cb) {
    this._write(new NullStatsdRecord(
        'ms',
        name,
        null,
        null,
        time
    ));
    process.nextTick(cb);
};

proto.getChildClient = function() {
    return new NullStatsd(this._buffer.capacity());
};

<|endoftext|>