var path = require('path');
var webpack = require('webpack');

module.exports = {
  devtool: 'source-map',
  entry: [
    './src/index'
  ],
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js',
    publicPath: '/static/'
  },
  plugins: [
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.DefinePlugin({
      'process.env': {
        'NODE_ENV': JSON.stringify('production')
      }
    }),
    new webpack.optimize.UglifyJsPlugin({
      compressor: {
        warnings: false
      }
    })
  ],
  module: {
    loaders: [{
      test: /\.js$/,
      loaders: ['babel'],
      include: path.join(__dirname, 'src')
    }]
  }
};

var path = require('path');
var webpack = require('webpack');

module.exports = {
  devtool: 'source-map',
  entry: [
    './src/index'
  ],
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js',
    publicPath: '/static/'
  },
  plugins: [
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.DefinePlugin({
      'process.env': {
        'NODE_ENV': JSON.stringify('production')
      }
    }),
    new webpack.optimize.UglifyJsPlugin({
      compressor: {
        warnings: false
      }
    })
  ],
  module: {
    loaders: [{
      test: /\.js$/,
      include: path.join(__dirname, 'src')
      loader: 'babel',
      query: {
        'stage': 0,
        'plugins': ['react-transform'],
        'extra': {
          'react-transform': {
            'transforms': [{
              'transform': 'react-transform-hmr',
              'imports': ['react'],
              'locals': ['module']
            }, {
              'transform': 'react-transform-catch-errors',
              'imports': ['react', 'redbox-react']
            }]
          }
        }
      }
    }]
  }
};

Make babel-load safer when use other environment like gulp


var vows = require('vows');
var assert = require('assert');
var util = require('util');
var oauth = require('passport-http-oauth');

vows.describe('passport-http-oauth').addBatch({

  'should report a version': function () {
    assert.isString(oauth.version);
  },

  'should export strategies': function () {
    assert.isFunction(oauth.TokenStrategy);
  },

}).export(module);

var vows = require('vows');
var assert = require('assert');
var util = require('util');
var oauth = require('passport-http-oauth');

vows.describe('passport-http-oauth').addBatch({

  'should report a version': function () {
    assert.isString(oauth.version);
  },

  'should export strategies': function () {
    assert.isFunction(oauth.ClientStrategy);
    assert.strictEqual(oauth.ClientStrategy, oauth.ConsumerStrategy);
    assert.isFunction(oauth.TokenStrategy);
  },

}).export(module);

Test export of ClientStrategy, with alias to ConsumerStrategy.


var _ = require('../index.js'),
    test = require('tape');

test('pluck: maintains original pluck after extension', function (t) {
    t.plan(1);

    var base = [
        {a: 1, p: 1},
        {b: 1, p: 2},
        {c: 1, p: 3},
        {d: 1, p: 4}
    ];

    var nestedProps = _.pluck(base, 'p');

    t.deepEqual(nestedProps, [1, 2, 3, 4]);
});

test('pluck: should extract values from a given nested property', function (t) {
    t.plan(1);

    var base = [
        {a: 1, p: {c: 1}},
        {b: 1, p: {c: 2}},
        {c: 1, p: {c: 3}},
        {d: 1, p: {c: 4}}
    ];

    var nestedProps = _.pluck(base, 'p.c');

    t.deepEqual(nestedProps, [1, 2, 3, 4]);
});

test('pluck: should extract values from a given nested property', function (t) {
    t.plan(1);

    var base = [
        {a: 1, p: {c: {d: 4}}},
        {b: 1, p: {c: {d: 1}}},
        {c: 1, p: {c: {d: 44}}},
        {d: 1, p: {c: 4}}
    ];

    var nestedProps = _.pluck(base, 'p.c.d');

    t.deepEqual(nestedProps, [4, 1, 44, undefined]);
});

Test deeply nested properties with undefined element


import Ember from 'ember';
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';

export default Ember.Route.extend(AuthenticatedRouteMixin, {
    model(params) {
        return this.store.findRecord('collection', params.collection_id);
    }
});

import Ember from 'ember';
import AuthenticatedRouteMixin from 'ember-simple-auth/mixins/authenticated-route-mixin';

export default Ember.Route.extend(AuthenticatedRouteMixin, {
    model(params) {
        return this.store.findRecord('collection', params.collection_id);
    },
    actions: {
        addNodeToCollection(projectId) {
            this.store.findRecord('node', projectId).then(node => {
                var collection = this.modelFor(this.routeName);
                collection.get('linkedNodes').pushObject(node);
                collection.save();
            });
        },
    }
});

Add action for adding collection.


module.exports = function(grunt) {
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-shell-spawn');
  grunt.initConfig({
    pkg: {
      main: grunt.file.readJSON("../src/package.json")
    },
    uglify: {
      main: {
        options: {
          banner: '/*! <%= pkg.main.name %> v<%= pkg.main.version %> created: <%= grunt.template.today("yyyy-mm-dd") %>*/'
        },
        files: [{
          expand: true,
          cwd: '../src',
          src: '**/*.js',
          dest: '../lib/js'
        }]
      }
    },
    shell: {
      proxy: {
        execOptions: {
          detached: true
        },
        command: "node ../lib/main/index.js"
      },
      digger: {
        execOptions: {
          detached: true
        },
        command: "node ../lib/digger/index.js"
      },
      finder: {
        execOptions: {
          detached: true
        },
        command: "node ../lib/finder/index.js"
      }
    }
  })
  grunt.registerTask('default', ['uglify:main', 'shell:proxy', 'shell:digger', 'shell:finder']);
}

module.exports = function(grunt) {
  grunt.file.setBase('..');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-shell-spawn');
  grunt.initConfig({
    pkg: {
      main: grunt.file.readJSON("../src/package.json")
    },
    uglify: {
      main: {
        options: {
          banner: '/*! <%= pkg.main.name %> v<%= pkg.main.version %> created: <%= grunt.template.today("yyyy-mm-dd") %>*/'
        },
        files: [{
          expand: true,
          cwd: '../src',
          src: '**/*.js',
          dest: '../lib/js'
        }]
      }
    },
    shell: {
      proxy: {
        execOptions: {
          detached: true
        },
        command: "node ../lib/main/index.js"
      },
      digger: {
        execOptions: {
          detached: true
        },
        command: "node ../lib/digger/index.js"
      },
      finder: {
        execOptions: {
          detached: true
        },
        command: "node ../lib/finder/index.js"
      }
    }
  })
  grunt.registerTask('default', ['uglify:main', 'shell:proxy', 'shell:digger', 'shell:finder']);
}

Fix the grunt base path


/*
	Example usage:

	var A = Class(function() {

		var defaults = {
			foo: 'cat',
			bar: 'dum'
		}

		this.init = function(opts) {
			opts = std.extend(opts, defaults)
			this._foo = opts.foo
			this._bar = opts.bar
		}

		this.getFoo = function() {
			return this._foo
		}

		this.getBar = function() {
			return this._bar
		}
	})

	var a = new A({ bar:'sim' })
	a.getFoo() == 'cat'
	a.getBar() == 'sim'
*/

var create = require('std/create')

module.exports = function extend(target, extendWith) {
	target = target ? create(target) : {}
	for (var key in extendWith) {
		if (typeof target[key] != 'undefined') { continue }
		target[key] = extendWith[key]
	}
	return target
}

/*
	Example usage:

	var A = Class(function() {

		var defaults = {
			foo: 'cat',
			bar: 'dum'
		}

		this.init = function(opts) {
			opts = std.extend(opts, defaults)
			this._foo = opts.foo
			this._bar = opts.bar
		}

		this.getFoo = function() {
			return this._foo
		}

		this.getBar = function() {
			return this._bar
		}
	})

	var a = new A({ bar:'sim' })
	a.getFoo() == 'cat'
	a.getBar() == 'sim'
*/

var copy = require('std/copy')

module.exports = function extend(target, extendWith) {
	target = target ? copy(target) : {}
	for (var key in extendWith) {
		if (typeof target[key] != 'undefined') { continue }
		target[key] = extendWith[key]
	}
	return target
}

Use copy instead of create


module.exports = {
  root: false,
  plugins: ['markdown'],
  globals: {
    expect: false
  },
  rules: {
    'no-unused-vars': 0,
    'no-undef': 0
  },
  parser: 'esprima',
  parserOptions: {
    tolerant: true
  }
};

module.exports = {
  root: false,
  plugins: ['markdown'],
  globals: {
    expect: true // One of the snippets overwrites the global
  },
  rules: {
    'no-unused-vars': 0,
    'no-undef': 0
  },
  parser: 'esprima',
  parserOptions: {
    tolerant: true
  }
};

Fix the last error by specifying expect:true in the eslint global setting


import React from 'react';
import { shallow } from 'enzyme';

import Form from '../index';

const renderComponent = (props = {}) => shallow(
  <Form {...props} />
);

describe('<Form />', () => {
  it('Expect to display a form element', () => {
    const renderedComponent = renderComponent();
    expect(renderedComponent.find('form')).toHaveLength(1);
  });

  describe('simulate events', () => {
    it('should submit the form', () => {
      const onSubmit = jest.fn();
      const renderedComponent = renderComponent({
        onSubmit,
      });
      renderedComponent.find('form').simulate('click');
      expect(onSubmit).toHaveBeenCalled();
    });
  });
});

import React from 'react';
import { shallow } from 'enzyme';

import Form from '../index';

const renderComponent = (props = {}) => shallow(
  <Form {...props}>
    <button type="submit">Submit</button>
  </Form>
);

describe('<Form />', () => {
  it('Expect to display a form element', () => {
    const renderedComponent = renderComponent();
    expect(renderedComponent.find('form')).toHaveLength(1);
  });

  describe('simulate events', () => {
    it('should submit the form', () => {
      const onSubmit = jest.fn();
      const renderedComponent = renderComponent({
        onSubmit,
      });
      renderedComponent.find('form').simulate('submit');
      expect(onSubmit).toHaveBeenCalled();
    });
  });
});

Update <Form /> simulate behavior


$(document).ready(function() {

  configureDataTables();
  configureCodeBox();

});

function configureDataTables(){

    $('#problem-table').dataTable( {
        "iDisplayLength": 25,
        "aaSorting": [[ 3, "desc" ]],
        "aoColumns": [
            null,
            null,
            null,
            null
        ]
    } );

    $('#user-table').dataTable( {
        "iDisplayLength":25,
        "aaSorting": [[ 0, "asc" ]],
        "aoColumns": [
	    null,
            null,
            null
        ]
    } );
}

function configureCodeBox(){
    //For no javascript version we have the code-box text area
    //If we have javascript on then we remove it and replace it with
    //the proper div
    $('#code-box').replaceWith("

");
    var hiddenCodeInput = "<input type=\"hidden\" value=\"blank\" name=\"code\" id=\"code\">";
    $(hiddenCodeInput).insertBefore('#id');

    if ($("#run-button").length){
       var editor = ace.edit("editor");
       editor.setTheme("ace/theme/textmate");

       var ClojureMode = require("ace/mode/clojure").Mode;
       editor.getSession().setMode(new ClojureMode());
       document.getElementById('editor').style.fontSize='13px';
       $("#run-button").click(function(){
         var text = editor.getSession().getValue();
         $('#code').val(text);
       });
}

}

$(document).ready(function() {

  configureDataTables();
  configureCodeBox();

});

function configureDataTables(){

    $('#problem-table').dataTable( {
        "iDisplayLength": 25,
        "aaSorting": [[ 3, "desc" ]],
        "aoColumns": [
            null,
            null,
            null,
            null
        ]
    } );

    $('#user-table').dataTable( {
        "iDisplayLength":25,
        "aaSorting": [[ 0, "asc" ]],
        "aoColumns": [
	    null,
            null,
            null
        ]
    } );
}

function configureCodeBox(){
    //For no javascript version we have the code-box text area
    //If we have javascript on then we remove it and replace it with
    //the proper div
    var oldBox = $('#code-box');
    oldBox.replaceWith("

" + oldBox.val() + "

");
    var hiddenCodeInput = "<input type=\"hidden\" value=\"blank\" name=\"code\" id=\"code\">";
    $(hiddenCodeInput).insertBefore('#id');

    if ($("#run-button").length){
       var editor = ace.edit("editor");
       editor.setTheme("ace/theme/textmate");

       var ClojureMode = require("ace/mode/clojure").Mode;
       editor.getSession().setMode(new ClojureMode());
       document.getElementById('editor').style.fontSize='13px';
       $("#run-button").click(function(){
         var text = editor.getSession().getValue();
         $('#code').val(text);
       });
}

}

Make Ace save the user's code on failures


// Author: Daniel G (oscar-daniel.gonzalez@hp.com)

// Reserved for comms
chrome.runtime.onMessage.addListener(function(msg)
{
  alert("Popup - Yo I got a message!");
  console.debug(msg);
});

// Inject tridion_ext into page
var scr = document.createElement('script');
scr.type="text/javascript";
scr.src= chrome.extension.getURL('js/tridion_ext.js');
document.head.appendChild(scr);

window.addEventListener("message", function(event) {
  // We only accept messages from ourselves
  if (event.source != window)
    return;

  switch(event.data.action){
    case "open_item" :
    case "init_levels":
      chrome.runtime.sendMessage(event.data);
      break;
    case "get_publishable_batches":
      get_publishable_batches();
    default:
      break;
  }
  if (event.data.action && (event.data.action == "open_item" || event.data.action == "init_levels"))    chrome.runtime.sendMessage(event.data);

}, false);

function get_publishable_batches(){
  // Get all publishable batches
  console.debug("gettin publishable batches!");
  chrome.storage.local.get(null,(storage)=>{
    if(!storage.cust_batches) return;

    var publishable_batches = [];
    storage.cust_batches.forEach((cust_batch)=>{
      if(cust_batch.publishable) publishable_batches.push(cust_batch);
    });
    window.postMessage({"action":"publishable_batches", "data": publishable_batches},"*");
  })
}

// Author: Daniel G (oscar-daniel.gonzalez@hp.com)

// Reserved for comms
chrome.runtime.onMessage.addListener(function(msg)
{
  alert("Popup - Yo I got a message!");
  console.debug(msg);
});

// Inject tridion_ext into page
var scr = document.createElement('script');
scr.type="text/javascript";
scr.src= chrome.extension.getURL('js/tridion_ext.js');
document.head.appendChild(scr);

window.addEventListener("message", function(event) {
  // We only accept messages from ourselves
  if (event.source != window)
    return;

  switch(event.data.action){
    case "open_item" :
    case "init_levels":
      chrome.runtime.sendMessage(event.data);
      break;
    case "get_publishable_batches":
      get_publishable_batches();
    default:
      break;
  }
}, false);

function get_publishable_batches(){
  // Get all publishable batches
  console.debug("gettin publishable batches!");
  chrome.storage.local.get(null,(storage)=>{
    if(!storage.cust_batches) return;

    var publishable_batches = [];
    storage.cust_batches.forEach((cust_batch)=>{
      if(cust_batch.publishable) publishable_batches.push(cust_batch);
    });
    window.postMessage({"action":"publishable_batches", "data": publishable_batches},"*");
  })
}

Fix double messaging for multi opening


'use strict';

module.exports = appleLinkTags;

var hasTarget = require('./has-target');

function appleLinkTags(manifest, config) {
  if (manifest.apple === false) {
    return [];
  }

  var links = [];
  var sizes;
  var rootURL = config.rootURL || '/';

  var precomposed;

  if(manifest.apple && manifest.apple.precomposed) {
    precomposed = '-precomposed';
  } else {
    precomposed = '';
  }

  if (manifest.icons && manifest.icons.length) {
    for(var icon of manifest.icons) {
      if (!icon.targets || hasTarget(icon, 'apple')) {
        if (icon.sizes) {
          sizes = ` sizes="${icon.sizes}"`
        } else {
          sizes = '';
        }

        links.push(`<link rel="apple-touch-icon${precomposed}" href="${rootURL}${icon.src.replace(/^\//,'')}"${sizes}>`);
      }
    }
  }

  return links;
}

'use strict';

module.exports = appleLinkTags;

var hasTarget = require('./has-target');

function appleLinkTags(manifest, config) {
  if (manifest.apple === false) {
    return [];
  }

  var links = [];
  var sizes;
  var rootURL = config.rootURL || '/';

  var precomposed;

  if(manifest.apple && manifest.apple.precomposed) {
    precomposed = '-precomposed';
  } else {
    precomposed = '';
  }

  if (manifest.icons && manifest.icons.length) {
    for(var icon of manifest.icons) {
      if (!icon.targets || hasTarget(icon, 'apple')) {
        if (icon.sizes) {
          sizes = ` sizes="${icon.sizes}"`
        } else {
          sizes = '';
        }

        if (/^https?:\/\//i.test(icon.src)) {
          rootURL = '';
        }

        links.push(`<link rel="apple-touch-icon${precomposed}" href="${rootURL}${icon.src.replace(/^\//,'')}"${sizes}>`);
      }
    }
  }

  return links;
}

Support absolute urls in ios icon meta


// Place your application-specific JavaScript functions and classes here
// FIXME: Tell people how Sprockets and Coffe works
//
//= require jquery
//= require jquery_ujs
//= require_tree .

Add default require directives for jquery


(function(global) {
  global.NativeFeatures = {
    Promise: !!global.Promise,
    Symbol: !!global.Symbol,
    Map: !!global.Map,
    Set: !!global.Set
  };
}(this));

(function(global) {
  global.NativeFeatures = {
    Promise: !!global.Promise,
    Symbol: !!global.Symbol,
    Map: !!global.Map,
    Set: !!global.Set
  };
}(typeof global !== 'undefined' ? global : this));

Fix native features check under node


import { toArray, Class } from './lib/objects';
import { uuid } from './lib/uuid';

/**
 Transforms represent a set of operations that are applied against a
 source. After a transform has been applied, it should be assigned the
 `result`, a `TransformResult` that represents the result of the transform.

 Transforms are automatically assigned a UUID `id`.

 @class Transform
 @namespace Orbit
 @param {Array}     [operations] Operations to apply
 @param {Object}    [options]
 @param {String}    [options.id] Unique id for this transform (will be assigned a uuid by default)
 @constructor
 */
var Transform = Class.extend({
  operations: null,

  init: function(ops, options) {
    this.operations = toArray(ops);

    options = options || {};

    this.id = options.id || uuid();
  },

  isEmpty: function() {
    return this.operations.length === 0;
  }
});

Transform.from = function(transformOrOperations) {
  if (transformOrOperations instanceof Transform) { return transformOrOperations; }
  return new Transform(transformOrOperations);
};

export default Transform;

import { toArray, Class } from './lib/objects';
import { uuid } from './lib/uuid';

/**
 Transforms represent a set of operations that are applied against a
 source. After a transform has been applied, it should be assigned the
 `result`, a `TransformResult` that represents the result of the transform.

 Transforms are automatically assigned a UUID `id`.

 @class Transform
 @namespace Orbit
 @param {Array}     [operations] Operations to apply
 @param {Object}    [options]
 @param {String}    [options.id] Unique id for this transform (will be assigned a uuid by default)
 @constructor
 */
export default class Transform {
  constructor(ops, _options) {
    this.operations = toArray(ops);

    let options = _options || {};

    this.id = options.id || uuid();
  }

  isEmpty() {
    return this.operations.length === 0;
  }
}

Transform.from = function(transformOrOperations) {
  if (transformOrOperations instanceof Transform) { return transformOrOperations; }
  return new Transform(transformOrOperations);
};

Convert Transform to ES class.


var async = require('async');
var _ = require('lodash');

/**
 * pollCount - return the sum of all votes for a poll
 *
 * @param  {Object} args requires pollId
 * @return {Object}      count as the sum of the values of the poll
 */
function pollCount (args, done) {
  var seneca = this;
  var plugin = args.role;
  var ENTITY_NS = ('cd/polls_results');
  var pollId = args.pollId;
  seneca.make$(ENTITY_NS).list$(["SELECT sum(CAST (value AS INTEGER)), count(*) FROM cd_polls_results WHERE poll_id = $1 AND value ~ '([0-9])+'", pollId], function(err, count){
    if(err) return done(err);
    var result = 0;
    var participation = 0;
    if (count.length > 0) {
      result = count[0].sum;
      participation = count[0].count;
    }
    done(null, {sum: result, count: participation});
  });
}

module.exports = pollCount;

var async = require('async');
var _ = require('lodash');

/**
 * pollCount - return the sum of all votes for a poll
 *
 * @param  {Object} args requires pollId
 * @return {Object}      count as the sum of the values of the poll
 */
function pollCount (args, done) {
  var seneca = this;
  var plugin = args.role;
  var ENTITY_NS = ('cd/polls_results');
  var pollId = args.pollId;
  seneca.make$(ENTITY_NS).list$(["SELECT sum(CAST (value AS INTEGER)), count(*) FROM cd_polls_results WHERE poll_id = $1 AND value ~ '^([0-9])+$'", pollId], function(err, count){
    if(err) return done(err);
    var result = 0;
    var participation = 0;
    if (count.length > 0) {
      result = count[0].sum;
      participation = count[0].count;
    }
    done(null, {sum: result, count: participation});
  });
}

module.exports = pollCount;

Enforce regexp to start and end with an integer


import React from 'react';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';

import { logoutUser } from '../../redux/actions';

const NavBar = ({ isAuthenticated, logoutUser }) => (

<Link to="/">Home</Link>

<Link to="/history">History</Link>

<Link to="/history/april">April</Link>

<Link to="/stopwatch">Stopwatch</Link>

<Link to="/signup">Signup</Link>

        { !isAuthenticated &&

                <Link to="/login">Login</Link>

        }
        { isAuthenticated &&

                <button onClick={ logoutUser }>Logout</button>

        }

);

export default connect(
    ({ root }) => ({ isAuthenticated: root.isAuthenticated }),
    { logoutUser }
)(NavBar);

import React from 'react';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';

import { logoutUser } from '../../redux/actions';

const NavBar = ({ isAuthenticated, logoutUser }) => (

<Link to="/">Home</Link>

        { isAuthenticated &&
            [

<Link to="/history">History</Link>
,

<Link to="/history/april">April</Link>
,

<Link to="/stopwatch">Stopwatch</Link>

            ]
        }
        { !isAuthenticated &&
            [

<Link to="/signup">Signup</Link>
,

                    <Link to="/login">Login</Link>

            ]
        }
        { isAuthenticated &&

                <button onClick={ logoutUser }>Logout</button>

        }

);

export default connect(
    ({ root }) => ({ isAuthenticated: root.isAuthenticated }),
    { logoutUser }
)(NavBar);

Hide navbar links if user not authenticated


import React from 'react'
import {NavLink} from 'react-router-dom'
import Auth from '../auth/authenticator'
import '../styles/Navbar.css'

function logout(event) {
  event.preventDefault();
  Auth.logOut();
}

const Navbar = () => {
  if (Auth.loggedIn()) {
    return (

          <NavLink
            className="navlink"
            to="/newsfeed"
          >Home</NavLink>
          <NavLink
            className="navlink"
            to="/sources"
          >Sources</NavLink>
           {logout(e)}}
          >Logout

    )
  } else {
    return (

          <NavLink
            className="navlink"
            to="/"
          >Home</NavLink>
          <NavLink
            className="navlink"
            to="/sources"
          >Sources</NavLink>

    )
  }
}

export default Navbar

import React, {Component} from 'react'
import {NavLink} from 'react-router-dom'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'

import * as sessionsActions from '../actions/sessionsActions'
import Auth from '../auth/authenticator'
import '../styles/Navbar.css'

class Navbar extends Component {
  constructor(props) {
    super();
    this.logout = this.logout.bind(this)
  }

  logout(event) {
    event.preventDefault();
    this.props.actions.logOutUser();
  }

  render() {
    if (this.props.auth.isAuthenticated) {
      return (

            <NavLink
              className="navlink"
              to="/newsfeed"
            >Home</NavLink>
            <NavLink
              className="navlink"
              to="/sources"
            >Sources</NavLink>
             {this.logout(e)}}
            >Logout

      )
    } else {
      return (

            <NavLink
              className="navlink"
              to="/"
            >Home</NavLink>
            <NavLink
              className="navlink"
              to="/sources"
            >Sources</NavLink>

      )
    }
  }

}

const mapStateToProps = (state) => {
  return {auth: state.auth}
}

const mapDispatchToProps = (dispatch) => {
  return {actions: bindActionCreators(sessionsActions, dispatch)}
}
export default connect(mapStateToProps, mapDispatchToProps)(Navbar)

Connect to state and actions, refactor conditional rendering and logout


'use strict';

var minify = require('html-minifier').minify;

function minifyHTML(opts) {
    if (!opts) opts = {};

    function minifier(req, res, next) {

        var sendMinified = function (err, html) {
            if (err) {
                console.error(err)
                if (opts.displayErrors === true) {
                    res.send('Rendering error: ' + err.message);
                } else {
                    res.sendStatus(500);
                }
            } else {
                html = minify(html, opts.htmlMinifier);
                res.send(html);
            }
        };

        if (opts.override === false) {
            res.renderMin = function (view, renderOpts) {
                this.render(view, renderOpts, sendMinified);
            }
        } else {
            res.oldRender = res.render;
            res.render = function (view, renderOpts) {
                this.oldRender(view, renderOpts, sendMinified);
            };
        }

        return next();
    }

    return (minifier);
}

module.exports = minifyHTML;

'use strict';

var minify = require('html-minifier').minify;

function minifyHTML(opts) {
    if (!opts) opts = {};

    function minifier(req, res, next) {

        var sendMinified = function (callback) {

            // No callbak specified, just minify and send to client.
            if (typeof callback === 'undefined') {
                return function (err, html) {
                    if (err) {
                        console.error(err)
                        if (opts.displayErrors === true) {
                            res.send('Rendering error: ' + err.message);
                        } else {
                            res.sendStatus(500);
                        }
                    } else {
                        html = minify(html, opts.htmlMinifier);
                        res.send(html);
                    }
                }
            } else {

                // Custom callback specified by user, use that one
                return function (err, html) {
                    html = minify(html, opts.htmlMinifier);
                    callback(err, html);
                }
            }
        };

        if (opts.override === false) {
            res.renderMin = function (view, renderOpts, callback) {
                this.render(view, renderOpts, sendMinified(callback));
            }
        } else {
            res.oldRender = res.render;
            res.render = function (view, renderOpts, callback) {
                this.oldRender(view, renderOpts, sendMinified(callback));
            };
        }

        return next();
    }

    return (minifier);
}

module.exports = minifyHTML;

Add option for adding a callback


const { assert } = require('chai');

const KeyCode = require('./dist/keycode.cjs.js');
const { defineTests } = require('./dist/test-definitions.cjs');

// Tests for Node (Common JS) Module.
defineTests(KeyCode, {
  test: it,
  assertEquals: assert.equal
});

const { assert } = require('chai');

const KeyCode = require('./dist/keycode.cjs');
const { defineTests } = require('./dist/test-definitions.cjs');

// Tests for Node (Common JS) Module.
defineTests(KeyCode, {
  test: it,
  assertEquals: assert.equal
});

Remove .js from the require


import { chai } from 'meteor/practicalmeteor:chai';
import { setup, breakdown } from './setup';

const { TemplateInstance } = Blaze;

describe('setup', function () {
  beforeEach(function () {
      breakdown();
  });

  it('should add functions to the TemplateInstance prototype', function () {
      setup();

      chai.expect(TemplateInstance.prototype.gqlQuery).to.be.ok;
  });
});

import { chai } from 'meteor/practicalmeteor:chai';
import { setup, breakdown } from './setup';

const { TemplateInstance } = Blaze;

describe('setup', function () {
  beforeEach(function () {
      breakdown();
  });

  it('should add functions to the TemplateInstance prototype', function () {
      setup();

      chai.expect(TemplateInstance.prototype.gqlQuery).to.be.ok;
      chai.expect(TemplateInstance.prototype.queriesReady).to.be.ok;
  });
});

Test is queriesReady is available


import knex from 'knex';
// import pg from 'pg';

import config from './config';

// Use ssl by default
// pg.defaults.ssl = true;

export default knex(config.db);

/**
 * Builds SQL query with given filter object.
 * Returns rows matching all given fields (default), or any given field.
 *
 * Sample usage:
 *
 * knex('users')
 *   .where(likeFilter({
 *     name: 'foo',
 *     email: '@bar.com'
 *   }))
 */
export const likeFilter = (filters, anyField = false) => (origQuery) => {
  let q = origQuery;

  Object.keys(filters).forEach((key, index) => {
    if (!index) {
      // first field with .whereRaw()
      q = q.whereRaw(`LOWER(${key}) LIKE '%' || LOWER(?) || '%'`, filters[key]);
    } else if (anyField) {
      // if anyField true, additional fields use .orWhereRaw() (any field must match)
      q = q.orWhereRaw(`LOWER(${key}) LIKE '%' || LOWER(?) || '%'`, filters[key]);
    } else {
      // by default additional fields use .andWhereRaw() (all fields must match)
      q = q.andWhereRaw(`LOWER(${key}) LIKE '%' || LOWER(?) || '%'`, filters[key]);
    }
  });

  return q;
};

Add likeFilter helper method for easy filtering as per query string


'use strict';

/**
 * Cron config that gives you an opportunity
 * to run scheduled jobs.
 *
 * The cron format consists of:
 * [MINUTE] [HOUR] [DAY OF MONTH] [MONTH OF YEAR] [DAY OF WEEK] [YEAR (optional)]
 */

module.exports = {

  /**
   * Simple example.
   * Every monday at 1am.
   */

  // '0 1 * * 1': function () {
  //
  // }
};

'use strict';

/**
 * Cron config that gives you an opportunity
 * to run scheduled jobs.
 *
 * The cron format consists of:
 * [MINUTE] [HOUR] [DAY OF MONTH] [MONTH OF YEAR] [DAY OF WEEK] [YEAR (optional)]
 */

module.exports = {

  /**
   * Simple example.
   * Every monday at 1am.
   */

  // '0 1 * * 1': () => {
  //
  // }
};

Use arrow function in CRON file


#!/usr/bin/env node

const CFonts = require('cfonts')
const args = require('../libs/args')
const prompt = require('../libs/prompt')
const Whale = require('../index')

prompt.then((answer) => {
  CFonts.say('Whale, a Ethereum and Bitcoin price board for geeks|Loading...', {
    font: 'console',
    align: 'left',
    colors: ['candy'],
    letterSpacing: 1,
    lineHeight: 1.8,
    space: true,
    maxLength: '0'
  })

  new Whale(args, answer.pairs.join(','))
})

#!/usr/bin/env node

const CFonts = require('cfonts')
const args = require('../libs/args')
const prompt = require('../libs/prompt')
const Whale = require('../index')

prompt.then((answer) => {
  CFonts.say('WHALE, a Ethereum and Bitcoin price board for geeks|Loading...', {
    font: 'console',
    align: 'left',
    colors: ['candy'],
    letterSpacing: 1,
    lineHeight: 1.8,
    space: true,
    maxLength: '0'
  })

  new Whale(args, answer.exchange, answer.markets)
})

Change some data and typo


#!/usr/bin/env node

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

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

var argv = minimist(process.argv.slice(2));

if (argv._[0] === 'init') {
  require('./init')();
}
else {
  var base = process.cwd();
  var nwitchPath;
  try {
    nwitchPath = resolve('nwitch', {basedir: base});
  } catch (error) {
    nwitchPath = findup('lib/index.js');
  }

  if (!nwitchPath) {
    logger.error('Unable to find local nwitch.');
    logger.error('Did you run `npm install nwitch`?');
  }
  else {
    var configFile = path.resolve(base, './config.toml');
    require(nwitchPath)(configFile);
  }
}

#!/usr/bin/env node

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

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

var argv = minimist(process.argv.slice(2), {
    alias: {v: 'version'}
});

if (argv._[0] === 'init') {
  require('./init')();
}
else if (argv.v) {
  logger.info(require('../package.json').version);
}
else {
  var base = process.cwd();
  var nwitchPath;
  try {
    nwitchPath = resolve('nwitch', {basedir: base});
  } catch (error) {
    nwitchPath = findup('lib/index.js');
  }

  if (!nwitchPath) {
    logger.error('Unable to find local nwitch.');
    logger.error('Did you run `npm install nwitch`?');
  }
  else {
    var configFile = path.resolve(base, './config.toml');
    require(nwitchPath)(configFile);
  }
}

Add `-v` and `--version` flags


// app.js

var Curiosity = angular.module('curiosity', ['elasticsearch', 'ui.select2', 'ui.bootstrap', 'ngAnimate', 'gd.ui.jsonexplorer']);
Curiosity.service('elasticClient', function(esFactory) {
		return {
			getClient: function(server) {
          	  return esFactory({
            	    host: server,
            	});
        	}
   		}
   	}
);

// add this to allow controler in custom result template
Curiosity.config(['$controllerProvider', function($controllerProvider) {
  // this option might be handy for migrating old apps, but please don't use it
  // in new ones!
  $controllerProvider.allowGlobals();
}]);

Add parameter to be compatible with old template


import React from 'react';
import PaddedView from '@ui/PaddedView';
import BackgroundView from '@ui/BackgroundView';
import SavedPaymentReviewForm from '@ui/forms/SavedPaymentReviewForm';

import { Title } from '../styles';

const PaymentMethodConfirmation = () => (
  <BackgroundView>
    <PaddedView>
      <Title>Review</Title>
    </PaddedView>
    <SavedPaymentReviewForm
      navigateToOnComplete="done"
    />
  </BackgroundView>
);

export default PaymentMethodConfirmation;

import React from 'react';
import { compose, mapProps } from 'recompose';
import { withRouter } from '@ui/NativeWebRouter';
import BackgroundView from '@ui/BackgroundView';
import SavedPaymentReviewForm from '@ui/forms/SavedPaymentReviewForm';
import PaddedView from '@ui/PaddedView';
import { Title, Row, TinyButton, TinyButtonText } from '../styles';

const enhance = compose(
  withRouter,
  mapProps(props => ({
    onPressEdit() {
      props.history.push('address');
    },
  })),
);

const PaymentMethodConfirmation = enhance(({ onPressEdit }) => (
  <BackgroundView>
    <PaddedView>
      <Row>
        <Title>Review</Title>
        <TinyButton onPress={onPressEdit}>
          <TinyButtonText>Edit</TinyButtonText>
        </TinyButton>
      </Row>
    </PaddedView>
    <SavedPaymentReviewForm
      navigateToOnComplete="done"
    />
  </BackgroundView>
));

export default PaymentMethodConfirmation;

Add "Edit" button to Add Payment Review screen


"use strict";

describe('Footer component', () => {
    let element = undefined;
    let $rootScope = undefined;
    let $compile = undefined;

    let mod = angular.module('tests.footer', []).service('Authentication', function () {
        this.check = false;
        this.attempt = credentials => {
            if (credentials.username == 'test' && credentials.password == 'test') {
                this.check = true;
            }
        };
        this.status = () => this.check;
    });
    beforeEach(angular.mock.module(mod.name));

    beforeEach(inject((_$rootScope_, _$compile_) => {
        $rootScope = _$rootScope_;
        $compile = _$compile_;
    }));

    describe('Footer while not logged in', () => {
        it('should only display one li', () => {
            let tpl = angular.element('<monad-footer></monad-footer>');
            element = $compile(tpl)($rootScope);
            $rootScope.$digest();
            expect(element.find('li').length).toBe(1);
        });
    });
});

"use strict";

describe('Footer component', () => {
    let element = undefined;
    let $rootScope = undefined;
    let $compile = undefined;
    let Authentication = undefined;

    let mod = angular.module('tests.footer', []).service('Authentication', function () {
        this.check = false;
        this.attempt = credentials => {
            if (credentials.username == 'test' && credentials.password == 'test') {
                this.check = true;
            }
        };
        this.status = () => $rootScope.check;
    });
    beforeEach(angular.mock.module(mod.name));

    beforeEach(inject((_$rootScope_, _$compile_, _Authentication_) => {
        $rootScope = _$rootScope_;
        $compile = _$compile_;
        Authentication = _Authentication_;
    }));

    describe('Footer while not logged in', () => {
        it('should only display one li', () => {
            let tpl = angular.element('<monad-footer></monad-footer>');
            element = $compile(tpl)($rootScope);
            $rootScope.$digest();
            expect(element.find('li').length).toBe(1);
        });
    });

    describe('Footer while logged in', () => {
        it('should display two lis', () => {
            Authentication.check = true;
            let tpl = angular.element('<monad-footer></monad-footer>');
            element = $compile(tpl)($rootScope);
            $rootScope.$digest();
            expect(element.find('li').length).toBe(2);
            Authentication.check = false;
        });
    });
});

Test footer while logged in


'use strict';

module.exports = function(grunt) {
    var path = require('path');
    var shell = require('shelljs');

    var bin = ['node_modules', '.bin'].join(path.sep);

    var lsc = [bin, 'lsc'].join(path.sep);
    var mocha = [bin, 'mocha'].join(path.sep);
    var npm = 'npm';

    grunt.registerTask('livescript_src', 'update LiveScript source', function () {
        var done = this.async();
        // FIXME: Compile changed file only
        shell.exec(lsc + ' -c lib');
        shell.exec(lsc + ' -c test');
        grunt.task.run('mocha');
        done();
    });

    grunt.registerTask('package_ls', 'update package.ls', function () {
        var done = this.async();
        shell.exec(lsc + ' -cj package.ls');
        shell.exec(npm + ' install');
        done();
    });

    grunt.registerTask('mocha', 'run mocha', function () {
        var done = this.async();
        shell.exec(mocha);
        done();
    });

    grunt.initConfig({
        watch: {
            livescript_src: {
                files: ['lib/**/*.ls', 'test/**/*.ls'],
                tasks: ['livescript_src']
            },
            package_ls: {
                files: ['package.ls'],
                tasks: ['package_ls']
            }
        }
    });

    grunt.loadNpmTasks('grunt-contrib-watch');

    grunt.registerTask('default', ['watch']);
};

'use strict';

module.exports = function(grunt) {
    var path = require('path');
    var shell = require('shelljs');

    var bin = ['node_modules', '.bin'].join(path.sep);

    var lsc = [bin, 'lsc'].join(path.sep);
    var npm = 'npm';

    grunt.registerTask('livescript_src', 'update LiveScript source', function () {
        var done = this.async();
        // FIXME: Compile changed file only
        shell.exec(lsc + ' -c lib');
        shell.exec(lsc + ' -c test');
        grunt.task.run('test');
        done();
    });

    grunt.registerTask('package_ls', 'update package.ls', function () {
        var done = this.async();
        shell.exec(lsc + ' -cj package.ls');
        shell.exec(npm + ' install');
        done();
    });

    grunt.registerTask('test', 'run test', function () {
        var done = this.async();
        shell.exec(npm + ' test');
        done();
    });

    grunt.initConfig({
        watch: {
            livescript_src: {
                files: ['lib/**/*.ls', 'test/**/*.ls'],
                tasks: ['livescript_src']
            },
            package_ls: {
                files: ['package.ls'],
                tasks: ['package_ls']
            }
        }
    });

    grunt.loadNpmTasks('grunt-contrib-watch');

    grunt.registerTask('default', ['watch']);
};

Use `npm test' to run test in grunt


$(document).ready(function() {
    $(document).keyup(function(e) {
        var tag = e.target.tagName.toLowerCase();
        if (tag != 'input' && tag != 'textarea' && tag != 'select' && !e.ctrlKey) {
            if (e.keyCode==78 || e.keyCode==77) {
                $('.nav-menu-icon').trigger('click');
            } else if (e.keyCode==65) {
                $('.search-menu-icon').trigger('click');
            } else if (e.keyCode==73 && e.shiftKey) {
                $( "#new-ip" ).click();
            } else if (e.keyCode==73) {
                $( "#new-indicator" ).click();
            } else if (e.keyCode==69 && e.shiftKey) {
                $( "#new-event" ).click();
            } else if (e.keyCode==69) {
                $( "#new-email-yaml" ).click();
            } else if (e.keyCode==68) {
                $( "#new-domain" ).click();
            } else if (e.keyCode==80) {
                $( "#new-pcap" ).click();
            } else if (e.keyCode==83) {
                $( "#new-sample" ).click();
            } else if (e.keyCode==83) {
                $( "#new-signature" ).click();
            } else if (e.keyCode==27) {
                $( ".mm-opened").trigger('close');
            } else if (e.shiftKey && e.keyCode==191) {
                $( "#shortcut-keys").click();
            }
        }
    });
});

$(document).ready(function() {
    $(document).keyup(function(e) {
        var tag = e.target.tagName.toLowerCase();
        if (tag != 'input' && tag != 'textarea' && tag != 'select' && !e.ctrlKey) {
            if (e.keyCode==78 || e.keyCode==77) {
                $('.nav-menu-icon').trigger('click');
            } else if (e.keyCode==65) {
                $('.search-menu-icon').trigger('click');
            } else if (e.keyCode==73 && e.shiftKey) {
                $( "#new-ip" ).click();
            } else if (e.keyCode==73) {
                $( "#new-indicator" ).click();
            } else if (e.keyCode==69 && e.shiftKey) {
                $( "#new-event" ).click();
            } else if (e.keyCode==69) {
                $( "#new-email-yaml" ).click();
            } else if (e.keyCode==68) {
                $( "#new-domain" ).click();
            } else if (e.keyCode==80) {
                $( "#new-pcap" ).click();
            } else if (e.keyCode==83) {
                $( "#new-sample" ).click();
            } else if (e.keyCode==71) {
                $( "#new-signature" ).click();
            } else if (e.keyCode==27) {
                $( ".mm-opened").trigger('close');
            } else if (e.shiftKey && e.keyCode==191) {
                $( "#shortcut-keys").click();
            }
        }
    });
});

Make the ASCII keyCode unique for the Signature object


import React from "react";

import { shallow } from "enzyme";
import toJson from "enzyme-to-json";

import moment from "moment";

import DateSlider from "../src/DateSlider";

describe("DateSlider Component", () => {
  it("should shallow render without issues", () => {
    const component = shallow(<DateSlider />);

    expect(component.length).toBe(1);
    expect(toJson(component)).toMatchSnapshot();
  });

  it("should render a DateSliderComponent", () => {
    const isoStartDay = 4;
    const onDateSelected = jest.fn();
    const onWeekChanged = jest.fn();
    const selectedDate = new moment();
    const component = shallow(
      <DateSlider
        isoStartDay={isoStartDay}
        onDateSelected={onDateSelected}
        onWeekChanged={onWeekChanged}
        selectedDate={selectedDate}
      />
    );

    expect(component.name()).toBe("DateSliderComponent");
  });
});

import React from "react";

import { shallow } from "enzyme";
import toJson from "enzyme-to-json";

import moment from "moment";

import DateSlider from "../src/DateSlider";

describe("DateSlider Component", () => {
  it("should shallow render without issues", () => {
    const component = shallow(
      <DateSlider selectedDate={moment.utc("2017-05-11")} />
    );

    expect(component.length).toBe(1);
    expect(toJson(component)).toMatchSnapshot();
  });

  it("should render a DateSliderComponent", () => {
    const isoStartDay = 4;
    const onDateSelected = jest.fn();
    const onWeekChanged = jest.fn();
    const selectedDate = new moment();
    const component = shallow(
      <DateSlider
        isoStartDay={isoStartDay}
        onDateSelected={onDateSelected}
        onWeekChanged={onWeekChanged}
        selectedDate={selectedDate}
      />
    );

    expect(component.name()).toBe("DateSliderComponent");
  });
});

Set snapshot to fixed date rather than using today


import React from 'react';
import styled, { css } from 'styled-components';
import PropTypes from 'prop-types';
import { transitionOpacity } from 'mixins';
import HeaderButton from 'components/HeaderButton';
import theme from 'theme';

const StyledContainer = styled.div`
    display: flex;
    position: absolute;
    width: 100%;
    height: 100%;
    ${transitionOpacity}
`;

const closeBar = css`
    background: ${theme.black};
    content: '';
    height: 3px;
    width: 20px;
    position: absolute;
    top: 7px;
    left: -1px;
`;

const CloseSearch = styled.div`
    height: 18px;
    width: 18px;
    position: relative;
    &::after {
        ${closeBar}
        transform: rotate(45deg);
    }
    &::before {
        ${closeBar}
        transform: rotate(-45deg);
    }
`;

const StyledInput = styled.input`
    flex: 1 0 calc(100% - 65px);
    padding-left: 25px;
`;

const Search = (props) => {
    return (
        <StyledContainer show={props.show}>
            <StyledInput type="text" placeholder="Find a movie" />
            <HeaderButton>
                <CloseSearch onClick={props.close} />
            </HeaderButton>
        </StyledContainer>
    );
}

Search.propTypes = {
    close: PropTypes.func.isRequired,
    show: PropTypes.bool.isRequired,
};

export default Search;

import React from 'react';
import styled, { css } from 'styled-components';
import PropTypes from 'prop-types';
import { transitionOpacity } from 'mixins';
import HeaderButton from 'components/HeaderButton';
import theme from 'theme';

const StyledContainer = styled.div`
    display: flex;
    position: absolute;
    width: 100%;
    height: 100%;
    ${transitionOpacity}
`;

const closeBar = css`
    background: ${theme.black};
    content: '';
    height: 3px;
    width: 20px;
    position: absolute;
    top: 7px;
    left: -1px;
`;

const CloseSearch = styled.div`
    height: 18px;
    width: 18px;
    position: relative;
    &::after {
        ${closeBar}
        transform: rotate(45deg);
    }
    &::before {
        ${closeBar}
        transform: rotate(-45deg);
    }
`;

const StyledInput = styled.input`
    border: 0;
    flex: 1 0 calc(100% - 65px);
    padding-left: 25px;
`;

const Search = (props) => {
    return (
        <StyledContainer show={props.show}>
            <StyledInput type="text" placeholder="Find a movie" />
            <HeaderButton>
                <CloseSearch onClick={props.close} />
            </HeaderButton>
        </StyledContainer>
    );
}

Search.propTypes = {
    close: PropTypes.func.isRequired,
    show: PropTypes.bool.isRequired,
};

export default Search;

Remove border from search input


/**
 *  Base webpack config, extended by ./Build based on options.
 *  See ../gulpfile.babel.js for usage.
 */
export default {
  progress: true,              // Shows progress when compiling on the CLI

  entry  : ['babel-polyfill'], // Base entries (Only for requires)
  devtool: 'source-map',       // Only when not compressing

  plugins: [],

  resolve: {
    extensions: ['', '.js', '.jsx'],
  },

  module: {
    loaders: [
      {
        test: /\.less$/,
        loader: 'style-loader!css-loader!less-loader',
      },
      {
        test: /\.css$/,
        loader: 'style-loader!css-loader',
      },
      {
        test: /\.(png|jpg|gif|woff|woff2|eot|svg)$/,
        loader: 'url-loader?limit=8192',
      },
      {
        test: /\.json$/,
        loader: 'json-loader',
      },
    ],

    /*

    preLoaders: [],
    postLoaders: [],

    noParse: [ /node_modules/ ],

    // Disable handling of unknown requires
    unknownContextRegExp: /$^/,
    unknownContextCritical: false,

    // Disable handling of requires with a single expression
    exprContextRegExp: /$^/,
    exprContextCritical: false,

    // Warn for every expression in require
    wrappedContextCritical: true

    */
  },
};

/**
 *  Base webpack config, extended by ./Build based on options.
 *  See ../gulpfile.babel.js for usage.
 */
export default {
  progress: true,              // Shows progress when compiling on the CLI

  entry  : ['babel-polyfill'], // Base entries (Only for requires)
  devtool: 'source-map',       // Only when not compressing

  plugins: [],

  resolve: {
    extensions: ['', '.js', '.jsx', '.json'],
  },

  module: {
    loaders: [
      {
        test: /\.less$/,
        loader: 'style-loader!css-loader!less-loader',
      },
      {
        test: /\.css$/,
        loader: 'style-loader!css-loader',
      },
      {
        test: /\.(png|jpg|gif|woff|woff2|eot|svg)$/,
        loader: 'url-loader?limit=8192',
      },
      {
        test: /\.json$/,
        loader: 'json-loader',
      },
    ],

    /*

    preLoaders: [],
    postLoaders: [],

    noParse: [ /node_modules/ ],

    // Disable handling of unknown requires
    unknownContextRegExp: /$^/,
    unknownContextCritical: false,

    // Disable handling of requires with a single expression
    exprContextRegExp: /$^/,
    exprContextCritical: false,

    // Warn for every expression in require
    wrappedContextCritical: true

    */
  },
};

Update webpack to include json


import React, { Component } from 'react';

import { createSession } from '../../src'
import ConnectionStatus from './ConnectionStatus';
import Publisher from './Publisher';
import Subscribers from './Subscribers';

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

    this.state = {
      streams: [],
      connected: false
    };

    this.setConnected = this.setStateValue.bind(this, 'connected');
    this.setStreams = this.setStateValue.bind(this, 'streams');

    this.sessionEventHandlers = {
      sessionConnected: this.setConnected.bind(this, true),
      sessionDisconnected: this.setConnected.bind(this, false)
    };
  }

  setStateValue(key, value) {
    this.setState({ [key]: value });
  }

  componentWillMount() {
    this.sessionHelper = createSession({
      apiKey: this.props.apiKey,
      sessionId: this.props.sessionId,
      token: this.props.token,
      onStreamsUpdated: this.setStreams
    });
    this.sessionHelper.session.on(this.sessionEventHandlers);
  }

  componentWillUnmount() {
    this.sessionHelper.session.off(this.sessionEventHandlers);
    this.sessionHelper.disconnect();
  }

  render() {
    return (
      <div>
        <ConnectionStatus connected={this.state.connected} />
        <Publisher session={this.sessionHelper.session} />
        <Subscribers
          session={this.sessionHelper.session}
          streams={this.state.streams}
        />
      </div>
    );
  }
}

import React, { Component } from 'react';

import { OTSession, OTStreams } from '../../src'
import ConnectionStatus from './ConnectionStatus';
import Publisher from './Publisher';
import Subscriber from './Subscriber';

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

    this.state = {
      connected: false
    };

    this.sessionEvents = {
      sessionConnected: () => {
        this.setState({ connected: true });
      },
      sessionDisconnected: () => {
        this.setState({ connected: false });
      }
    };
  }

  render() {
    return (
      <OTSession
        apiKey={this.props.apiKey}
        sessionId={this.props.sessionId}
        token={this.props.token}
        eventHandlers={this.sessionEvents}
      >
        <ConnectionStatus connected={this.state.connected} />
        <Publisher />
        <OTStreams>
          <Subscriber />
        </OTStreams>
      </OTSession>
    );
  }
}

Replace createSession with OTSession in example app


App.GlossaViewport = Ext.extend(App.GlossaViewportUi, {
  initComponent: function() {
    // Property to keep track of SearchPanel instances for query building
    this.searchPanels = [];

    App.GlossaViewport.superclass.initComponent.call(this);

    this.setupSubcomponents();
    this.setupEventHandlers();
  },

  setupSubcomponents: function() {
    // Add an initial search panel which will not be closable
    this.addSearchPanel();
    this.doLayout();
  },

  setupEventHandlers: function() {
    this.addSearchButton.on('click', function() {
      this.addSearchPanel();
    }, this);
  },

  addSearchPanel: function() {
    this.centerTabpanel.add(this.createSearchPanel());
  },

  // function that has to be called when adding or deleting a SearchPanel
  // to the gui
  createSearchPanel: function() {
    panel = new App.Search.SearchPanel();
    this.registerSearchPanel(panel);
    return panel;
  },

  registerSearchPanel: function(panel) {
    this.searchPanels.push(panel);
  },

  // returns an object/hash that specifies the query constructed in the gui
  getQuerySpec: function() {
    // only got one SearchPanel at the moment
    return this.searchPanels[0].getQuerySpec();
  }
});

App.GlossaViewport = Ext.extend(App.GlossaViewportUi, {
  initComponent: function() {
    // Property to keep track of SearchPanel instances for query building
    this.searchPanels = [];

    App.GlossaViewport.superclass.initComponent.call(this);

    this.setupSubcomponents();
    this.setupEventHandlers();
  },

  setupSubcomponents: function() {
    // Add an initial search panel which will not be closable
    this.addSearchPanel();
    this.doLayout();
  },

  setupEventHandlers: function() {
    this.addSearchButton.on('click', function() {
      this.addSearchPanel();
    }, this);
  },

  addSearchPanel: function() {
    var newSearchPanel = this.createSearchPanel();
    this.centerTabpanel.add(newSearchPanel);
    this.centerTabpanel.setActiveTab(newSearchPanel.id);
  },

  // function that has to be called when adding or deleting a SearchPanel
  // to the gui
  createSearchPanel: function() {
    panel = new App.Search.SearchPanel();
    this.registerSearchPanel(panel);
    return panel;
  },

  registerSearchPanel: function(panel) {
    this.searchPanels.push(panel);
  },

  // returns an object/hash that specifies the query constructed in the gui
  getQuerySpec: function() {
    // only got one SearchPanel at the moment
    return this.searchPanels[0].getQuerySpec();
  }
});

Switch to new search panel after it is created


/**
 * This is the entrypoint for the Chai bundle used as part of the test
 * environment. Chai is only distributed as Common JS, so it must be bundled.
 */

export * from 'chai/index.mjs';

/**
 * This is the entrypoint for the Chai bundle used as part of the test
 * environment. Chai is only distributed as Common JS, so it must be bundled.
 *
 * Despite the `.mjs` extension, the module referenced here[^1] imports another
 * file[^2] that itself attempts to import the entire library using `require()`.
 *
 * [^1]: https://github.com/chaijs/chai/blob/v4.3.6/index.mjs
 * [^2]: https://github.com/chaijs/chai/blob/v4.3.6/index.js
 */

export * from 'chai/index.mjs';

Add a note about why Chai must be bundled despite having a module entrypoint.


/**
 * Created by pivotal on 5/19/17.
 */
require('dotenv').config()

describe('chrome extension is loaded properly when feature tests run', function () {
  beforeEach(function () {
    jasmine.getEnv().defaultTimeoutInterval = 1000000
  })

  it('creates a WWLTW chore in the backlog', function () {
    browser.setValue("[data-test='tracker-api-token'] input", process.env.TEST_PIVOTAL_TRACKER_TOKEN)
    browser.click('button=Submit')
    browser.pause(1000)
    browser.click('label=Test Project')
    browser.pause(1000)

    browser.url('https://www.pivotaltracker.com/signin')
    browser.setValue("#credentials_username", process.env.TEST_PIVOTAL_TRACKER_USERNAME)
    browser.click("#login_type_check_form input[type='submit']")
    browser.setValue("#credentials_password", process.env.TEST_PIVOTAL_TRACKER_PASSWORD )
    browser.click("#login_type_check_form input[type='submit']")
    browser.click("a=Test Project")
    browser.pause(1000)

    expect(browser.getText(".story_name*=WWLTW for the week of")).toMatch(/WWLTW for the week of \d{1,2}\/\d{1,2}/)
  })
})

/**
 * Created by pivotal on 5/19/17.
 */
require('dotenv').config()

describe('chrome extension is loaded properly when feature tests run', function () {
  it('creates a WWLTW chore in the backlog', function () {
    browser.setValue("[data-test='tracker-api-token'] input", process.env.TEST_PIVOTAL_TRACKER_TOKEN)
    browser.click('button=Submit')
    browser.pause(1000)
    browser.click('label=Test Project')
    browser.pause(1000)

    browser.url('https://www.pivotaltracker.com/signin')
    browser.setValue("#credentials_username", process.env.TEST_PIVOTAL_TRACKER_USERNAME)
    browser.click("#login_type_check_form input[type='submit']")
    browser.setValue("#credentials_password", process.env.TEST_PIVOTAL_TRACKER_PASSWORD )
    browser.click("#login_type_check_form input[type='submit']")
    browser.click("a=Test Project")
    browser.pause(1000)

    expect(browser.getText(".story_name*=WWLTW for the week of")).toMatch(/WWLTW for the week of \d{1,2}\/\d{1,2}/)
  })
})

Remove code overriding default jasmine timeout interval


import { shallowMount } from '@vue/test-utils';
import App from '@/App';

// see https://vue-test-utils.vuejs.org/guides/using-with-vue-router.html#testing-components-that-use-router-link-or-router-view
describe('App component should', () => {
  it('render without crashing', () => {
    const wrapper = shallowMount(App, {
      stubs: ['router-link', 'router-view']
    });
    expect(wrapper.find('hello')).toBeDefined();
  });
});

import { shallowMount } from '@vue/test-utils';
import App from '@/App';

// see https://vue-test-utils.vuejs.org/guides/using-with-vue-router.html#testing-components-that-use-router-link-or-router-view
describe('App component should', () => {
  it('render without crashing', () => {
    const wrapper = shallowMount(App, {
      stubs: ['router-link', 'router-view']
    });
    expect(wrapper.html()).toContain('<div id="nav">')
  });
});

Fix App jest test because it is otherwise always green no matter what is in find()


var kickass = require('../index');

var params = {
  q: 'test',
  field:'seeders',
  order:'desc'
}

describe('kickass', function(){
    it('should contain an array of torrents', function(done) {
        kickass(params, function(err, result) {
            expect(err).toBeNull();
            expect(result.list.length).not.toBe(0);
            result.list.forEach(function(element) {
                expect(element.title).not.toBeNull();
                expect(element.link).not.toBeNull();
                expect(element.guid).not.toBeNull();
                expect(element.pubDate).not.toBeNull();
                expect(element.torrentLink).not.toBeNull();
                expect(element.files).not.toBeNull();
                expect(element.comments).not.toBeNull();
                expect(element.hash).not.toBeNull();
                expect(element.peers).not.toBeNull();
                expect(element.seeds).not.toBeNull();
                expect(element.leechs).not.toBeNull();
                expect(element.size).toBeGreaterThan(0);
                expect(element.votes).not.toBeNull();
                expect(element.verified).not.toBeNull();
            })
            done();
        })
    });

    it("should return an empty list", function(done) {
        params.q = "3d8f7c6e91bbaa6766948ec13320533f"
        kickass(params, function(err, result) {
            expect(err).toBeNull();
            expect(result.list.length).toBe(0);
            done();
        });
    })
});

var kickass = require('../index');

var params = {
  q: 'test',
  field:'seeders',
  order:'desc'
}

describe('kickass', function(){
    it('should contain an array of torrents', function(done) {
        kickass(params, function(err, result) {
            expect(err).toBeNull();
            expect(result.list.length).not.toBe(0);
            result.list.forEach(function(element) {
                expect(element.title).not.toBeNull();
                expect(element.link).not.toBeNull();
                expect(element.guid).not.toBeNull();
                expect(element.pubDate).not.toBeNull();
                expect(element.torrentLink).not.toBeNull();
                expect(element.files).not.toBeNull();
                expect(element.comments).not.toBeNull();
                expect(element.hash).not.toBeNull();
                expect(element.peers).not.toBeNull();
                expect(element.seeds).not.toBeNull();
                expect(element.leechs).not.toBeNull();
                expect(element.size).toBeGreaterThan(0);
                expect(element.votes).not.toBeNull();
                expect(element.verified).not.toBeNull();
            })
            done();
        })
    });

    it('should return an empty list', function(done) {
        params.q = '3d8f7c6e91bbaa6766948ec13320533f';
        kickass(params, function(err, result) {
            expect(err).toBeNull();
            expect(result.list.length).toBe(0);
            done();
        });
    })
});

Use single quotes to reflect the existing conversion


define(['underscore'], function(_){
   var templates = {
      pull: '\
      <a target="_blank" href="<%- pull.url() %>" class="list-group-item pull">\

#<%- pull.number %> - <%- pull.title %>
\
      ',

      restore: '<button class="btn btn-primary navbar-btn" style="display: none" type="button">\
            <%- restore.title %>\
            \
      </button>',

      column: '
\
            <div class="click-heading panel-heading" data-toggle="collapse" data-target="#<%- column.id %>">\

\
                  <%- column.title %>\
                  \

\

\
         <div id="<%- column.id %>" class="list-group collapse in">
\

'
   };

   var compiledTemplates = {};

   return {
      get: function(name) {
         if (!compiledTemplates[name]) {
            compiledTemplates[name] = _.template(
               templates[name],
               null,
               { variable: name }
            );
         }
         return compiledTemplates[name];
      }
   };
});

define(['underscore', 'text!pull.html', 'text!restore.html', 'text!column.html'],
function(_, pull, restore, column){
   var templates = {
      pull: pull,
      restore: restore,
      column: column
   };

   var compiledTemplates = {};

   return {
      get: function(name) {
         if (!compiledTemplates[name]) {
            compiledTemplates[name] = _.template(
               templates[name],
               null,
               { variable: name }
            );
         }
         return compiledTemplates[name];
      }
   };
});

Switch from string templates to file templates


class Base {
  get sound() {
    return 'I am a ' + this.type + '.';
  }
}

class Animal extends Base {}

class Cat extends Animal {
  get type() { return 'cat'; }

  get sound() {
    return super.sound + ' MEOW!';
  }
}

assert.equal(new Cat().sound, 'I am a cat. MEOW!');

class Base {
  get sound() {
    return 'I am a ' + this.type + '.';
  }

  get name() {
    return this._name;
  }

  set name(val) {
    this._name = val;
  }
}

class Animal extends Base {}

class Cat extends Animal {
  get type() { return 'cat'; }

  get sound() {
    return super.sound + ' MEOW!';
  }

  set name(val) {
    super.name = val;
    this._name += ' Cat';
  }
}

var cat = new Cat();

assert.equal(cat.sound, 'I am a cat. MEOW!');
cat.name = 'Nyan';
assert.equal(new Cat().name, 'Nyan Cat');

Add test for failing assignment to super setter.


var datastore = require('../lib/environment').datastore,
    util = require('util');

module.exports = DataModel;

function DataModel() {
}

DataModel.prototype.save = function () {
    datastore.set(this.model, this.id, this);
};

DataModel.prototype.del = function () {
    datastore.del(this.model, this.id);
};

DataModel.findOne = function (Model, key, callback) {
    datastore.get(Model.name, key, function (err, results) {
        callback(err, results === null ? null : new Model(results));
    });
};

DataModel.all = function (Model, callback) {
    datastore.get(Model.name, '*', function (err, results) {
        var map = {};
        var list = [];
        for (var idx in results) {
            map[idx] = new Model(results[idx]);
        }
        if (typeof callback === 'function') {
            callback(err, map);
        }
    });
};

module.exports.extend = function (Model) {
    util.inherits(Model, DataModel);
    for (var classmethod in DataModel) {
        Model[classmethod] = DataModel[classmethod].bind(Model, Model);
    }
};

var datastore = require('../lib/environment').datastore,
    util = require('util');

module.exports = DataModel;

function DataModel() {
}

DataModel.prototype.save = function () {
    datastore.set(this.model, this.id, this);
};

DataModel.prototype.del = function () {
    datastore.del(this.model, this.id);
};

DataModel.prototype.changeId = function (oldid) {
    datastore.del(this.model, oldid);
    datastore.set(this.model, this.id, this);
};

DataModel.findOne = function (Model, key, callback) {
    datastore.get(Model.name, key, function (err, results) {
        callback(err, results === null ? null : new Model(results));
    });
};

DataModel.all = function (Model, callback) {
    datastore.get(Model.name, '*', function (err, results) {
        var map = {};
        var list = [];
        for (var idx in results) {
            map[idx] = new Model(results[idx]);
        }
        if (typeof callback === 'function') {
            callback(err, map);
        }
    });
};

module.exports.extend = function (Model) {
    util.inherits(Model, DataModel);
    for (var classmethod in DataModel) {
        Model[classmethod] = DataModel[classmethod].bind(Model, Model);
    }
};

Add a function for notifying DataModels about ID changes


const Realm = require('realm');

const schema = {
  schema: [
    { name: 'Alert',
      properties: {
        slug: 'string',
        long: 'float',
        lat: 'float'
      }
    }
  ]
};

export function initDb() {
  return new Realm(schema);
}

export function read(realm, object, eager = false) {
  return eager ? Array.from(realm.objects(object)) : realm.objects(object);
}

export function write(realm, object, data) {
  realm.write(() => {
    realm.create(object, data);
  });
}

// To dump Realm db => Realm.clearTestState()

const Realm = require('realm');

const schema = {
  schema: [
    { name: 'Alert',
      properties: {
        areaId: { type: 'string', indexed: true },
        slug: { type: 'string', indexed: true },
        long: 'float',
        lat: 'float'
      }
    }
  ]
};

export function initDb() {
  return new Realm(schema);
}

// realm objects are lazy loaded by default. Not easy to debug
export function read(realm, object, eager = false) {
  return eager ? Array.from(realm.objects(object)) : realm.objects(object);
}

export function write(realm, object, data) {
  realm.write(() => {
    realm.create(object, data);
  });
}

Change sb schema and add comments


import Ember from 'ember';
const {isArray} = Ember;
const {keys} = Object;

export function e3BindScale(params) {
  let [scale, key] = params;
  if(scale) {
    var resultScale = function(data) {
      if(isArray(data)) {
        return data.map(item => {
          return scale(item, key);
        });
      } else {
        return scale(data, key);
      }
    };

    // Add the additional properties on this scale.
    keys(scale).forEach(key => {
      resultScale[key] = scale[key];
    });

    return resultScale;
  }
}

export default Ember.Helper.helper(e3BindScale);

import Ember from 'ember';
const {isArray, get} = Ember;
const {keys} = Object;

export function e3BindScale(params, options) {
  let {scaleDifference} = options;
  let [scale, key] = params;
  if(scale) {
    var resultScale = function(data) {
      if(isArray(data)) {
        return data.map(item => {
          return calculateValue(get(item, key), scale, scaleDifference);
        });
      } else {
        return calculateValue(get(data, key), scale, scaleDifference);
      }
    };

    // Add the additional properties on this scale.
    keys(scale).forEach(key => {
      resultScale[key] = scale[key];
    });

    return resultScale;
  }
}

function calculateValue(input, scale, scaleDifference) {
  let result = scale(input);

  /*
   Inverting the output would take the
   */
  if(scaleDifference) {
    let [r0, r1] = scale.range;
    result = r1 - r0 - result;
  }

  return result;
}

export default Ember.Helper.helper(e3BindScale);

Support Scale Different Option on Bind-scale


import Ember from 'ember';
import EditFormController from 'ember-flexberry/controllers/edit-form';

export default EditFormController.extend({
  /**
    Defaul style of modal context.

    @property readonly
    @type String
    @default #example
  */
  _style:'#example',

  actions: {
    modalWindow(style) {
      this.set('_style', style);
      let repeatWindow = Ember.$('#repeat-window').modal({
        closable: false,
        autofocus: false,
        detachable: false,
        allowMultiple: true,
        context: this.get('_style'),
      });
      this.set('repeatWindow', repeatWindow);
      this.get('repeatWindow').modal('show').modal('refresh');
    },

    modalWindowDouble(style) {
      this.set('_style', style);
      let repeatWindow = Ember.$('#repeat-window-double').modal({
        closable: false,
        autofocus: false,
        detachable: false,
        allowMultiple: true,
        context: this.get('_style'),
      });
      this.set('repeatWindowdouble', repeatWindow);
      this.get('repeatWindowdouble').modal('show').modal('refresh');
    },

    logOut() {
      this.get('repeatWindow').modal('hide');
    },

    logOutDouble() {
      this.get('repeatWindowdouble').modal('hide');
    }

  }
});

import Ember from 'ember';
import EditFormController from 'ember-flexberry/controllers/edit-form';

export default EditFormController.extend({
  /**
    Defaul style of modal context.

    @property readonly
    @type String
    @default #example
  */
  _style:'#example',

  actions: {
    modalWindow(style) {
      if (!Ember.isNone(style)) {
        this.set('_style', style);
      }

      let repeatWindow = Ember.$('#repeat-window').modal({
        closable: false,
        autofocus: false,
        detachable: false,
        allowMultiple: true,
        context: this.get('_style'),
      });
      this.set('repeatWindow', repeatWindow);
      this.get('repeatWindow').modal('show').modal('refresh');
    },

    modalWindowDouble(style) {
      if (!Ember.isNone(style)) {
        this.set('_style', style);
      }

      let repeatWindow = Ember.$('#repeat-window-double').modal({
        closable: false,
        autofocus: false,
        detachable: false,
        allowMultiple: true,
        context: this.get('_style'),
      });
      this.set('repeatWindowdouble', repeatWindow);
      this.get('repeatWindowdouble').modal('show').modal('refresh');
    },

    logOut() {
      this.get('repeatWindow').modal('hide');
    },

    logOutDouble() {
      this.get('repeatWindowdouble').modal('hide');
    }

  }
});

Add empty style parameter check


var Zopfli = require('./lib/zopfli');

exports.createGzip = function(options) {
  return new Zopfli('gzip', options);
};

exports.createZlib = function(options) {
  return new Zopfli('zlib', options);
};

exports.createDeflate = function(options) {
  return new Zopfli('deflate', options);
};

exports.gzip = function(buffer, options, callback) {
  Zopfli.gzip(buffer, options, callback);
};

exports.zlib = function(buffer, options, callback) {
  Zopfli.zlib(buffer, options, callback);
};

exports.deflate = function(buffer, options, callback) {
  zopfli.deflate(buffer, options, callback);
};

var Zopfli = require('./lib/zopfli');

exports.createGzip = function(options) {
  return new Zopfli('gzip', options);
};

exports.createZlib = function(options) {
  return new Zopfli('zlib', options);
};

exports.createDeflate = function(options) {
  return new Zopfli('deflate', options);
};

exports.gzip = function(buffer, options, callback) {
  Zopfli.gzip(buffer, options, callback);
};

exports.zlib = function(buffer, options, callback) {
  Zopfli.zlib(buffer, options, callback);
};

exports.deflate = function(buffer, options, callback) {
  Zopfli.deflate(buffer, options, callback);
};

Fix typo that caused ReferenceError


var View = require('../../lib/view.js');

var ConversationView = View.extend({
  template: require('./show.ractive'),
  eventNames: ['leave', 'toggleLock'],
  data: {
    firstName: function(user) {
      return user.getFirstName();
    },
    isLast: function(users, index) {
      return index == users.length - 1;
    }
  },

  /**
   * Leave the current conversation
   */
  leave: function(event) {
    app.get('user').leave();
  },

  /**
   * Locks the conversation, preventing other users from joining
   */
  toggleLock: function(event) {
    var conversation = this.get('user').get('conversation');
    conversation.set({locked: !conversation.get('locked')});
    conversation.save();
  }
});

module.exports = ConversationView;

var View = require('../../lib/view.js');

var ConversationView = View.extend({
  template: require('./show.ractive'),
  eventNames: ['leave', 'toggleLock'],
  data: {
    firstName: function(user) {
      return user.getFirstName();
    },
    isLast: function(users, index) {
      return index == users.length - 1 || index == users.length - 2 && users.at(users.length - 1).get('authorized');
    }
  },

  /**
   * Leave the current conversation
   */
  leave: function(event) {
    app.get('user').leave();
  },

  /**
   * Locks the conversation, preventing other users from joining
   */
  toggleLock: function(event) {
    var conversation = this.get('user').get('conversation');
    conversation.set({locked: !conversation.get('locked')});
    conversation.save();
  }
});

module.exports = ConversationView;

Fix user names listed in conversations including an additional comma under some circumstances


function parsePatch(x) {

  let reg = /(add|merge|remove)\s([\/[a-z0-9]+)(?:\s([0-9]+|\[[a-z0-9\-]+\]|\'[a-z0-9]+\'|\"[a-z0-9]+\"|{[a-z\s0-9{}"':,]+}))?/gi

  let found
  let results = []
  while ((found = reg.exec(x)) !== null) {
    let op = found[1]
    let path = found[2]
    let value = found[3]

    let patch = {
      op,
      path
    }

    if (op !== 'remove') {
      patch.value = value
    }

    results.push(patch)
  }

  return results
}

export default parsePatch

let text = '[a-z0-9\-+&\/]*'
let op = '(add|merge|replace)'
let separator = '\\s'
let path = '([\\/[a-z0-9]+)'
let valueObj = `({[a-z\\s0-9{}"':,]+})`

let valueNumber = `-?(?:(?:[1-9]\d*)|0)\.?\d*`
let valueText = `('.*?')`
let patchReg =
  op +
  separator +
  path +
  `(?:\\s([0-9]+|\\[[a-z0-9\-]+\\]|\\'[a-z0-9]+\\'|\\"[a-z0-9]+\\"|))?`

let updateReg =
  '(add|replace)' +
  separator +
  path +
  separator +
  '(?:' + valueText + '|' + valueNumber + ')'

let removeReg =
  '(remove)' +
  separator +
  path

let mergeReg =
  '(merge)' +
  separator +
  path +
  separator +
  valueObj

function parsePatch(x) {

  let reg = new RegExp(updateReg, 'gi')

  let found
  let results = []
  while ((found = reg.exec(x)) !== null) {
    let op = found[1]
    let path = found[2]
    let value = found[3] || found[4]

    let patch = {
      op,
      path
    }

    if (op !== 'remove') {
      patch.value = value
    }

    results.push(patch)
  }

  return results
}

export default parsePatch

Add complex regexp matching for patches.


var num = 0;
module.exports.inspect = (i) => {
  console.log('INSPECTOR #', ++num);
  console.log(i);
  return i;
};

const pluckUser = module.exports.pluckUser = (user) =>
  ({
    id: user.id,
    fbId: user.facebook_id,
    firstName: user.first_name,
    lastName: user.last_name,
    description: user.description,
    photoUrl: user.photo_url,
  });

module.exports.pluckUsers = (users) =>
  users.map((user) => pluckUser(user));

module.exports.pluckLanguages = (offerOrLearnResults) =>
  ({
    canTeach: offerOrLearnResults[0],
    willLearn: offerOrLearnResults[1],
  });

module.exports.pluckMatches = (matchesResults) => (
  matchesResults.map(matchResult => (
    {
      id: matchResult.teach_id,
      firstName: matchResult.teach_first,
      lastName: matchResult.teach_last,
      description: matchResult.teach_description,
      photoUrl: matchResult.teach_url,
      fbId: matchResult.teach_facebook_id,
    }
  ))
);

var num = 0;
module.exports.inspect = (a) => {
  console.log('INSPECTOR #', ++num);
  console.log(a);
  return a;
};

const pluckUser = module.exports.pluckUser = (user) =>
  ({
    id: user.id,
    fbId: user.facebook_id,
    firstName: user.first_name,
    lastName: user.last_name,
    description: user.description,
    photoUrl: user.photo_url,
  });

module.exports.pluckUsers = (users) =>
  users.map((user) => pluckUser(user));

module.exports.pluckLanguages = (offerOrLearnResults) =>
  ({
    canTeach: offerOrLearnResults[0],
    willLearn: offerOrLearnResults[1],
  });

module.exports.pluckMatches = (matchesResults) => (
  matchesResults.map(matchResult => (
    {
      id: matchResult.teach_id,
      firstName: matchResult.teach_first,
      lastName: matchResult.teach_last,
      description: matchResult.teach_description,
      photoUrl: matchResult.teach_url,
      fbId: matchResult.teach_facebook_id,
    }
  ))
);

Use a instead of as input to inspect


define(function(require) {
    'use strict';

    var ColumnManagerItemView;
    var $ = require('jquery');
    var BaseView = require('oroui/js/app/views/base/view');

    ColumnManagerItemView = BaseView.extend({
        template: require('tpl!orodatagrid/templates/column-manager/column-manager-item.html'),
        tagName: 'tr',

        attributes: function() {
            return {
                'data-cid': this.cid
            };
        },

        events: {
            'change input[type=checkbox][data-role=renderable]': 'onChangeVisibility'
        },

        listen: {
            // for some reason events delegated in view constructor does not work
            addedToParent: 'delegateEvents',
            // update view on model change
            'change:disabledVisibilityChange model': 'render',
            'change:renderable model': 'render'
        },

        /**
         * @inheritDoc
         */
        getTemplateData: function() {
            var data = ColumnManagerItemView.__super__.getTemplateData.call(this);
            data.cid = this.model.cid;
            return data;
        },

        /**
         * Handles DOM event for a column visibility change and updates model's attribute
         *
         * @param {jQuery.Event} e
         */
        onChangeVisibility: function(e) {
            var renderable = $(e.target).prop('checked');
            this.model.set('renderable', renderable);
        }
    });

    return ColumnManagerItemView;
});

define(function(require) {
    'use strict';

    var ColumnManagerItemView;
    var $ = require('jquery');
    var BaseView = require('oroui/js/app/views/base/view');

    ColumnManagerItemView = BaseView.extend({
        template: require('tpl!orodatagrid/templates/column-manager/column-manager-item.html'),
        tagName: 'tr',

        attributes: function() {
            return {
                'data-cid': this.cid
            };
        },

        events: {
            'change input[type=checkbox][data-role=renderable]': 'updateModel'
        },

        listen: {
            // for some reason events delegated in view constructor does not work
            addedToParent: 'delegateEvents',
            // update view on model change
            'change:disabledVisibilityChange model': 'render',
            'change:renderable model': 'updateView'
        },

        /**
         * @inheritDoc
         */
        getTemplateData: function() {
            var data = ColumnManagerItemView.__super__.getTemplateData.call(this);
            data.cid = this.model.cid;
            return data;
        },

        /**
         * Handles DOM event for a column visibility change and updates model's attribute
         *
         * @param {jQuery.Event} e
         */
        updateModel: function(e) {
            var renderable = $(e.target).prop('checked');
            this.model.set('renderable', renderable);
        },

        /**
         * Handles model event and updates the view
         */
        updateView: function() {
            var renderable = this.model.get('renderable');
            this.$('input[type=checkbox][data-role=renderable]').prop('checked', renderable);
        }
    });

    return ColumnManagerItemView;
});

Integrate column management with grid view functionality


var Promise = require('bluebird');

var ebs = require('./ebs');

var handler = function* (event, context) {
  try {

    yield ebs.snapshotVolumes();
    yield ebs.purgeSnapshots();

    context.done(null, 'Finished');
  } catch(e) {
    context.error('Error',  e);
  }
};

exports.handler = Promise.coroutine(handler);

//Uncomment below to test locally
exports.handler(null, {
  done: function(e, s) { console.log(s); },
  error: function(e, ex) { console.log(ex); }
});

var Promise = require('bluebird');

var ebs = require('./ebs');

var handler = function* (event, context, callback) {
  try {

    yield ebs.snapshotVolumes();
    yield ebs.purgeSnapshots();

    callback(null, 'Finished');
  } catch(e) {
    callback('Error',  e);
  }
};

exports.handler = Promise.coroutine(handler);

//Uncomment below to test locally
// exports.handler(null, null, function(e, s) {
//   if(e) {
//     console.log("ERROR!" + e);
//   }
//
//   console.log(s);
// });

Use callback instead of methods on context


const options = {
  duration: 700,
  easing: 'easeInOutQuint'
};

export default function defaultTransition(context) {
  if (!context || typeof context.transition !== 'function') {
    throw new Error('[bootstrap-modal] Invalid transitions context supplied');
  }

  return context.transition(
    context.hasClass('bootstrap-modal'),
    // hack to get reverse working..
    context.toValue(true),
    context.use('explode', {
      pick: '.modal-dialog',
      use: ['to-down', options]
    }, {
      pick: '.modal-backdrop',
      use: 'crossFade'
    }),
    context.reverse('explode', {
      pick: '.modal-dialog',
      use: ['to-up', options]
    }, {
      pick: '.modal-backdrop',
      use: 'crossFade'
    })
  );
}

const options = {
  duration: 700,
  easing: 'easeInOutQuint'
};
const crossOptions = {
  maxOpacity: 0.8
};

export default function defaultTransition(context) {
  if (!context || typeof context.transition !== 'function') {
    throw new Error('[bootstrap-modal] Invalid transitions context supplied');
  }

  return context.transition(
    context.hasClass('bootstrap-modal'),
    // hack to get reverse working..
    context.toValue(true),
    context.use('explode', {
      pick: '.modal-dialog',
      use: ['to-down', options]
    }, {
      pick: '.modal-backdrop',
      use: ['crossFade', crossOptions]
    }),
    context.reverse('explode', {
      pick: '.modal-dialog',
      use: ['to-up', options]
    }, {
      pick: '.modal-backdrop',
      use: ['crossFade', crossOptions]
    })
  );
}

Add maxOpacity for backdrop fade


//// [emptyAssignmentPatterns02_ES5.ts]

var a: any;
let x, y, z, a1, a2, a3;

({} = { x, y, z } = a);
([] = [ a1, a2, a3] = a);

//// [emptyAssignmentPatterns02_ES5.js]
var a;
var x, y, z, a1, a2, a3;
((x = a.x, y = a.y, z = a.z, a));
((a1 = a[0], a2 = a[1], a3 = a[2], a));

//// [emptyAssignmentPatterns02_ES5.d.ts]
declare var a: any;
declare let x: any, y: any, z: any, a1: any, a2: any, a3: any;

//// [emptyAssignmentPatterns02_ES5.ts]

var a: any;
let x, y, z, a1, a2, a3;

({} = { x, y, z } = a);
([] = [ a1, a2, a3] = a);

//// [emptyAssignmentPatterns02_ES5.js]
var a;
var x, y, z, a1, a2, a3;
(x = a.x, y = a.y, z = a.z, a);
(a1 = a[0], a2 = a[1], a3 = a[2], a);

//// [emptyAssignmentPatterns02_ES5.d.ts]
declare var a: any;
declare let x: any, y: any, z: any, a1: any, a2: any, a3: any;

Remove parentheses and accept baselines


"use strict";
/**
 * @module logger
 */
const log = require("loglevel");

// This is to demonstrate, that you can use any namespace you want.
// Namespaces allow you to turn on/off the logging for specific parts of the
// application.
// An idea would be to control this via an environment variable (on Node.js).
// See https://www.npmjs.com/package/debug to see how this could be implemented
// Part of #332 is introducing a logging library in the first place.
const DEFAULT_NAME_SPACE = "matrix";
const logger = log.getLogger(DEFAULT_NAME_SPACE);
log.setLevel(log.levels.WARN);

/**
 * Drop-in replacement for console using {@link https://www.npmjs.com/package/loglevel|loglevel}.
 * Can be tailored down to specific use cases if needed.
*/
module.exports = logger;

"use strict";
/**
 * @module logger
 */
const log = require("loglevel");

// This is to demonstrate, that you can use any namespace you want.
// Namespaces allow you to turn on/off the logging for specific parts of the
// application.
// An idea would be to control this via an environment variable (on Node.js).
// See https://www.npmjs.com/package/debug to see how this could be implemented
// Part of #332 is introducing a logging library in the first place.
const DEFAULT_NAME_SPACE = "matrix";
const logger = log.getLogger(DEFAULT_NAME_SPACE);
log.setLevel(log.levels.DEBUG);

/**
 * Drop-in replacement for console using {@link https://www.npmjs.com/package/loglevel|loglevel}.
 * Can be tailored down to specific use cases if needed.
*/
module.exports = logger;

Set loglevel to DEBUG to remain current behaviour.


import React from 'react';
import Article from './Article';

// note the functional nature of this declared object - does nore explicitly require a 'class' definition
const ArticleList = (props) => {
  return (
    <div>
      {Object.values(props.articles).map(article =>
        <Article
          key={article.id}
          article={article}
          author={props.authors[article.authorId]}
        />
      )}
    </div>
  );
};

export default ArticleList;

import React from 'react';
import Article from './Article';

// note the functional nature of this declared object - does nore explicitly require a 'class' definition
const ArticleList = (props) => {
  return (
    <div>
      {Object.values(props.articles).map((article) =>
        <Article
          key={article.id}
          article={article}
          author={props.authors[article.authorId]}
        />
      )}
    </div>
  );
};

export default ArticleList;

Update to correct Linting Warning


function redirectLogin() {
    window.location.href = '/log_in';
}

function likeComment(event, commentId) {
    console.log(forumId);
    console.log(commentId);
    $.ajax({
        'url': '/forums/' + forumId + '/comments/' + commentId + "/like",
        'type': 'PUT',
        'success': function(res) {
            console.log(res);
            $(event.target).children('p').text(res.likes.length);
            $(event.target).siblings('i').children('p').text(res.dislikes.length);
        },
        'error': function(err) {
            if (err) {
                // window.location.href = '/log_in';
                console.log(err);
            }
        },
        'dataType': 'json'
    })
}

function dislikeComment(event, commentId) {
    console.log(forumId);
    console.log(commentId);
    $.ajax({
        'url': '/forums/' + forumId + '/comments/' + commentId + "/dislike",
        'type': 'PUT',
        'success': function(res) {
            $(event.target).children('p').text(res.dislikes.length);
            $(event.target).siblings('i').children('p').text(res.likes.length);
        },
        'error': function(err) {
            if (err) {
                // window.location.href = '/log_in';
                console.log(err);
            }
        },
        'dataType': 'json'
    })
}

Add redirect to login endpoint if 401 received


const express = require('express');
const nunjucks = require('nunjucks');

const nextBusArrivals = require('./api/nextBusArrivals');

const app = express();

app.set('port', process.env.PORT || 4444);

// setup template engine
nunjucks.configure('./', {
    autoescape: true,
    express: app
});

app.set('view engine', 'nunjucks');

// routes
app.get('/', (req, res) => {
  // hard-coded for sanity testing
  nextBusArrivals('MTA NYCT_B63', 308209)
    .then((arrivals) => {
      res.render('index.html', {arrivals});
    });
});

app.listen(app.get('port'), () => {
  console.log(`listening on port ${app.get('port')}`)
})

const express = require('express');
const nunjucks = require('nunjucks');

const nextBusArrivals = require('./api/nextBusArrivals');

const app = express();

app.set('port', process.env.PORT || 4444);

// setup template engine
nunjucks.configure('./', {
    autoescape: true,
    express: app
});

app.set('view engine', 'nunjucks');

// routes
app.get('/', (req, res) => {
  nextBusArrivals(req.query.route, req.query.stop)
    .then((arrivals) => {
      res.render('index.html', {arrivals});
    });
});

app.listen(app.get('port'), () => {
  console.log(`listening on port ${app.get('port')}`)
})

Replace hardcoded API call with parameterized call


import React, { Component, Children } from 'react';
import PropTypes from 'prop-types';

export default class Switch extends Component {
  componentDidMount() {}
  render() {
    const children = Children.toArray(this.props.children);
    const caseToRender = children.filter(
      child => child.type.displayName === 'Case' && child.props.cond
    )[0];

    const defaultChild = children.filter(child => child.type.displayName === 'Default');

    if (
      defaultChild.length !== 1 ||
      !defaultChild[0]
    ) {
      throw new Error('There has to be exact one Default component');
    }

    const childToRender = caseToRender || defaultChild;

    return (
      <div className="">
        {childToRender}
      </div>
    );
  }
}

Switch.propTypes = {
  children: PropTypes.arrayOf(function (props, propName, componentName) {
    let error;
    const prop = props[propName];

    React.Children.forEach(prop, function (child) {
      if (
        !child ||
        !child.type ||
        !(child.type.displayName === 'Case' ||
        child.type.displayName === 'Default')
      ) {
        error = new Error(`${componentName} only accepts children of type Case or Default.`);
      }
    });

    return error;
  }).isRequired,
};

import React, { Component, Children } from 'react';
import PropTypes from 'prop-types';

export default class Switch extends Component {
  componentDidMount() {}
  render() {
    const children = Children.toArray(this.props.children);
    const caseToRender = children.filter(
      child => child.type.name === 'Case' && child.props.cond
    )[0];

    const defaultChild = children.filter(child => child.type.name === 'Default');

    if (
      defaultChild.length !== 1 ||
      !defaultChild[0]
    ) {
      throw new Error('There has to be exact one Default component');
    }

    const childToRender = caseToRender || defaultChild[0];

    return (
      <div className="">
        {childToRender}
      </div>
    );
  }
}

Switch.propTypes = {
  children: PropTypes.arrayOf(function (props, propName, componentName) {
    let error;
    const prop = props[propName];

    React.Children.forEach(prop, function (child) {
      if (
        !child ||
        !child.type ||
        !(child.type.name === 'Case' ||
        child.type.name === 'Default')
      ) {
        error = new Error(`${componentName} only accepts children of type Case or Default.`);
      }
    });

    return error;
  }).isRequired,
};

Use type.name to determine component type. displayName is only for debug


const passport = require('passport')
const passportJwt = require('passport-jwt')
const userModel = require('../models/users')
const { ExtractJwt, Strategy } = passportJwt

let jwtOptions = {}
jwtOptions.jwtFromRequest = ExtractJwt.fromAuthHeader()
jwtOptions.secretOrKey = process.env.JWT_SECRET

const strategy = new Strategy(jwtOptions, (jwtPayload, next) => {
  userModel.findOne(jwtPayload.username)
    .then(user => {
      next(null, user)
    })
    .catch(err => next(err, false))
})

passport.use(strategy)

module.exports = passport

const passport = require('passport')
const passportJwt = require('passport-jwt')
const userModel = require('../models/users')
const { ExtractJwt, Strategy } = passportJwt

let jwtOptions = {}
jwtOptions.jwtFromRequest = ExtractJwt.fromUrlQueryParameter('token')
jwtOptions.secretOrKey = process.env.JWT_SECRET

const strategy = new Strategy(jwtOptions, (jwtPayload, next) => {
  userModel.findOne(jwtPayload.username)
    .then(user => {
      next(null, user)
    })
    .catch(err => next(err, false))
})

passport.use(strategy)

module.exports = passport

Make passwport-jwt exract tokens from the query params instea of the AuthHeaders


'use strict';

let express = require('express');
let passport = require('passport');
let signToken = require('../auth.service').signToken;

var router = express.Router();

router.post('/', function (req, res, next) {
    passport.authenticate('local', (err, user, info) => {
        let error = err || info;
        if (error) {
            return res.status(401).json(error);
        }
        if (!user) {
            return res.status(404).json({message: 'Something went wrong, please try again.'});
        }

        let token = signToken(user._id, user.role.name);
        res.cookie('token', token);
        res.json({token: token});
    })(req, res, next);
});

module.exports = router;

'use strict';

let express = require('express');
let passport = require('passport');
let signToken = require('../auth.service').signToken;

var router = express.Router();

router.post('/', function (req, res, next) {
    passport.authenticate('local', (err, user, info) => {
        let error = err || info;
        if (error) {
            console.error(error);
            return res.status(401).json({message:error.message});
        }
        if (!user) {
            return res.status(404).json({message: 'Something went wrong, please try again.'});
        }

        let token = signToken(user._id, user.role.name);
        res.cookie('token', token);
        res.json({token: token});
    })(req, res, next);
});

module.exports = router;

Adjust in auth to avoid throwing full errors logs to end user.


import fs from 'fs';
import path from 'path';
import Sequelize from 'sequelize';

const basename = path.basename(module.filename);
const env = process.env.NODE_ENV || 'development';
const config = require(`${__dirname}/config/config.json`)[env];

config[env];
const db = {};

let sequelize;
if (config.use_env_variable) {
  sequelize = new Sequelize(process.env[config.use_env_variable]);
} else {
  sequelize = new Sequelize(
    config.database, config.username, config.password, config
  );
}

fs
  .readdirSync(__dirname)
  .filter(file =>
    (file.indexOf('.') !== 0) &&
    (file !== basename) &&
    (file.slice(-3) === '.js'))
  .forEach((file) => {
    const model = sequelize.import(path.join(__dirname, file));
    db[model.name] = model;
  });

Object.keys(db).forEach((modelName) => {
  if (db[modelName].associate) {
    db[modelName].associate(db);
  }
});

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;

import fs from 'fs';
import path from 'path';
import Sequelize from 'sequelize';

const basename = path.basename(module.filename);
const env = process.env.NODE_ENV || 'development';
const config = require(`${__dirname}/../config/config.json`)[env];

config[env];
const db = {};

let sequelize;
if (config.use_env_variable) {
  sequelize = new Sequelize(process.env[config.use_env_variable]);
} else {
  sequelize = new Sequelize(
    config.database, config.username, config.password, config
  );
}

fs
  .readdirSync(__dirname)
  .filter(file =>
    (file.indexOf('.') !== 0) &&
    (file !== basename) &&
    (file.slice(-3) === '.js'))
  .forEach((file) => {
    const model = sequelize.import(path.join(__dirname, file));
    db[model.name] = model;
  });

Object.keys(db).forEach((modelName) => {
  if (db[modelName].associate) {
    db[modelName].associate(db);
  }
});

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;

Fix file path for config.json