// This file has been autogenerated.

var profile = require('../../../lib/util/profile');

exports.getMockedProfile = function () {
  var newProfile = new profile.Profile();

  newProfile.addSubscription(new profile.Subscription({
    id: 'c2619f08-57f7-492b-a9c3-45dee233805b',
    name: 'kmsngtu Key Vault Account',
    user: {
      name: 'kmsngtu@microsoft.com',
      type: 'user'
    },
    tenantId: '72f988bf-86f1-41af-91ab-2d7cd011db47',
    registeredProviders: [],
    isDefault: true
  }, newProfile.environments['AzureCloud']));

  return newProfile;
};

exports.setEnvironment = function() {
  process.env['AZURE_ARM_TEST_LOCATION'] = 'West US';
};

exports.scopes = [];

// This file has been autogenerated.

var profile = require('../../../lib/util/profile');

exports.getMockedProfile = function () {
  var newProfile = new profile.Profile();

  newProfile.addSubscription(new profile.Subscription({
    id: 'c2619f08-57f7-492b-a9c3-45dee233805b',
    name: 'kmsngtu Key Vault Account',
    user: {
      name: 'kmsngtu@microsoft.com',
      type: 'user'
    },
    tenantId: '72f988bf-86f1-41af-91ab-2d7cd011db47',
    registeredProviders: [],
    isDefault: true
  }, newProfile.environments['AzureCloud']));

  return newProfile;
};

exports.setEnvironment = function() {
  process.env['AZURE_ARM_TEST_LOCATION'] = 'West US';
  process.env['AZURE_ARM_TEST_RESOURCE_GROUP'] = 'xplatTestVaultRG';
};

exports.scopes = [];

Add environment variable to test recordings.


/**
@module ember
@submodule ember-views
*/

var jQuery = (this && this.jQuery) || (Ember.imports && Ember.imports.jQuery);
if (!jQuery && typeof require === 'function') {
  jQuery = require('jquery');
}

Ember.assert("Ember Views require jQuery 1.7, 1.8, 1.9, 1.10, or 2.0", jQuery && (jQuery().jquery.match(/^((1\.(7|8|9|10))|2.0)(\.\d+)?(pre|rc\d?)?/) || Ember.ENV.FORCE_JQUERY));

/**
  Alias for jQuery

  @method $
  @for Ember
*/
Ember.$ = jQuery;

/**
@module ember
@submodule ember-views
*/

var jQuery = (this && this.jQuery) || (Ember.imports && Ember.imports.jQuery);
if (!jQuery && typeof require === 'function') {
  jQuery = require('jquery');
}

Ember.assert("Ember Views require jQuery between 1.7 and 2.1", jQuery && (jQuery().jquery.match(/^((1\.(7|8|9|10|11))|(2\.(0|1)))(\.\d+)?(pre|rc\d?)?/) || Ember.ENV.FORCE_JQUERY));

/**
  Alias for jQuery

  @method $
  @for Ember
*/
Ember.$ = jQuery;

Allow jQuery version 1.11 and 2.1


/*jslint browser: true, indent: 2 */
(function ($) {
  'use strict';
  $.fn.inviewport = function (options) {
    var settings = $.extend({
      'minPercentageInView' : 100,
      'standardClassName': 'in-view'
    }, options);
    this.each(function () {
      var $this = $(this),
        $win = $(window),
        changed = false,
        isVisible = function () {
          var c = settings.className || settings.standardClassName,
            min = (settings.threshold || settings.minPercentageInView) / 100,
            xMin = $this.width() * min,
            yMin = $this.height() * min,
            winPosX = $win.scrollLeft() + $win.width(),
            winPosY = $win.scrollTop() + $win.height(),
            elPosX = $this.offset().left + xMin,
            elPosY = $this.offset().top + yMin;
          if (winPosX > elPosX && winPosY > elPosY) {
            $this.addClass(c);
          }
        };
      $win.on('ready', isVisible())
        .on('resize scroll', function () {
          changed = true;
        })
      setInterval(function () {
        if (changed) {
          changed = false;
          isVisible();
        }
      }, 250);
    });
  };
}(jQuery));

/*jslint browser: true, indent: 2 */
(function ($) {
  'use strict';
  $.fn.inviewport = function (options) {
    var settings = $.extend({
      'minPercentageInView' : 100,
      'standardClassName': 'in-view'
    }, options);
    this.each(function () {
      var $this = $(this),
        $win = $(window),
        changed = false,
        isVisible = function () {
          var c = settings.className || settings.standardClassName,
            min = (settings.threshold || settings.minPercentageInView) / 100,
            xMin = $this.width() * min,
            yMin = $this.height() * min,
            winPosX = $win.scrollLeft() + $win.width(),
            winPosY = $win.scrollTop() + $win.height(),
            elPosX = $this.offset().left + xMin,
            elPosY = $this.offset().top + yMin;
          if (winPosX > elPosX && winPosY > elPosY) {
            if(!$this.hasClass(c)) $this.trigger("inviewport");
            $this.addClass(c);
          }
        };
      $win.on('ready', isVisible())
        .on('resize scroll', function () {
          changed = true;
        })
      setInterval(function () {
        if (changed) {
          changed = false;
          isVisible();
        }
      }, 250);
    });
  };
}(jQuery));

Add a custom event trigger


import {UnitState} from '../unit/constants';

export const API_URL = 'https://servicemat.hel.ninja/servicemap/v1'; //http://api.hel.fi/servicemap/v1';
export const DIGITRANSIT_API_URL = 'https://api.digitransit.fi/geocoding/v1';
export const APP_NAME = 'outdoors-sports-map';

export const DEFAULT_LANG = 'fi';

export const mobileBreakpoint = 768;

export type Action = {
  type: string,
  payload: Object
};

export type FetchAction = {
  type: string,
  payload: {
    params: Object
  }
};

export type EntityAction = {
  type: string,
  payload: {
    entities: Object,
    result: mixed
  }
};

export type AppState = {
  unit: UnitState
};

export type QueryValue = | string | Array<string>;

export const routerPaths = {
  singleUnit: 'unit/:unitId'
};

import {UnitState} from '../unit/constants';

export const API_URL = 'http://api.hel.fi/servicemap/v1';
export const DIGITRANSIT_API_URL = 'https://api.digitransit.fi/geocoding/v1';
export const APP_NAME = 'outdoors-sports-map';

export const DEFAULT_LANG = 'fi';

export const mobileBreakpoint = 768;

export type Action = {
  type: string,
  payload: Object
};

export type FetchAction = {
  type: string,
  payload: {
    params: Object
  }
};

export type EntityAction = {
  type: string,
  payload: {
    entities: Object,
    result: mixed
  }
};

export type AppState = {
  unit: UnitState
};

export type QueryValue = | string | Array<string>;

export const routerPaths = {
  singleUnit: 'unit/:unitId'
};

Change API URL to production one


(function() {

  var width, height;
  width = height = 600;

  window.samples.per_vertex_lighting = {

    initialize: function(canvas) {
      var scene = new THREE.Scene();

      var camera = new THREE.PerspectiveCamera( 75, width / height, 1, 1000 );
      camera.position.z = 100;

      var geometry = new THREE.SphereGeometry( 60, 4, 4 );
      var material = new THREE.MeshLambertMaterial( { color: 0xdddddd } );

      var mesh = new THREE.Mesh( geometry, material );
      scene.add( mesh );

      var spotLight = new THREE.SpotLight ( 0xffffffff );
      spotLight.position.set( 0, 100, 0 );
      scene.add( spotLight );

      var ambientLight = new THREE.AmbientLight( 0x22222222 );
      scene.add(ambientLight);

      var renderer = new THREE.WebGLRenderer({canvas: canvas});
      renderer.setSize( width, height);

      var instance = { active: false };
      function animate() {
        requestAnimationFrame( animate, canvas );
        mesh.material.wireframe = sample_defaults.wireframe;

        if(!instance.active || sample_defaults.paused) {
          // Rotate lighting around the X axis.
          var angle = 0.01;
          var matrix = new THREE.Matrix4().makeRotationX( angle );
          spotLight.position = matrix.multiplyVector3( spotLight.position );
        }

        renderer.render( scene, camera );
      }

      animate();
      return instance;
    }
  };
})();

(function() {

  var width, height;
  width = height = 600;

  window.samples.per_vertex_lighting = {

    initialize: function(canvas) {
      var scene = new THREE.Scene();

      var camera = new THREE.PerspectiveCamera( 75, width / height, 1, 1000 );
      camera.position.z = 100;

      var geometry = new THREE.SphereGeometry( 60, 4, 4 );
      var material = new THREE.MeshLambertMaterial( { color: 0xdddddd } );

      var mesh = new THREE.Mesh( geometry, material );
      scene.add( mesh );

      var spotLight = new THREE.SpotLight ( 0xffffffff );
      spotLight.position.set( 0, 100, 0 );
      scene.add( spotLight );

      var ambientLight = new THREE.AmbientLight( 0x22222222 );
      scene.add(ambientLight);

      var renderer = new THREE.WebGLRenderer({canvas: canvas});
      renderer.setSize( width, height);

      var instance = { active: false };
      function animate() {
        requestAnimationFrame( animate, canvas );
        mesh.material.wireframe = sample_defaults.wireframe;

        if(instance.active && !sample_defaults.paused) {
          // Rotate lighting around the X axis.
          var angle = 0.01;
          var matrix = new THREE.Matrix4().makeRotationX( angle );
          spotLight.position = matrix.multiplyVector3( spotLight.position );
        }

        renderer.render( scene, camera );
      }

      animate();
      return instance;
    }
  };
})();

Fix pause for per vertex lighting sample


(function() {
    'use strict';

    angular.module('facetApp')

    .directive('wsNavbar', wsNavbarDirective);

    /* @ngInject */
    function wsNavbarDirective($location, $templateRequest, $compile, $uibModal) {
        return {
            link: link,
            controller: NavbarController,
            controllerAs: 'vm'
        };

        function link(scope, elem) {
            var templateUrl;
            if ($location.host() === 'norssit.fi') {
                templateUrl = '/navbar-fi.html';
            } else {
                templateUrl = 'navbar-fi.html';
            }
            return $templateRequest(templateUrl)
            .then(function(template) {
                elem.html(template);
                return $templateRequest('views/subnavbar.html');
            }).then(function(template) {
                angular.element('#subnav').html(template);
                return $compile(elem.contents())(scope);
            });
        }

        function NavbarController() {
            var vm = this;

            vm.showHelp = showHelp;

            function showHelp() {
                $uibModal.open({
                    templateUrl: 'views/help.html',
                    size: 'lg'
                });
            }

        }
    }
})();

(function() {
    'use strict';

    angular.module('facetApp')

    .directive('wsNavbar', wsNavbarDirective);

    /* @ngInject */
    function wsNavbarDirective($location, $templateRequest, $compile, $uibModal) {
        return {
            link: link,
            controller: NavbarController,
            controllerAs: 'vm'
        };

        function link(scope, elem) {
            var templateUrl;
            if ($location.host() === 'www.norssit.fi') {
                templateUrl = '/navbar-fi.html';
            } else {
                templateUrl = 'navbar-fi.html';
            }
            return $templateRequest(templateUrl)
            .then(function(template) {
                elem.html(template);
                return $templateRequest('views/subnavbar.html');
            }).then(function(template) {
                angular.element('#subnav').html(template);
                return $compile(elem.contents())(scope);
            });
        }

        function NavbarController() {
            var vm = this;

            vm.showHelp = showHelp;

            function showHelp() {
                $uibModal.open({
                    templateUrl: 'views/help.html',
                    size: 'lg'
                });
            }

        }
    }
})();

Fix navbar loading (for real this time)


describe("Dropdown: ", function(){
  beforeEach(function(){
    loadFixtures('dropdown_fixture.html');
    locastyle.dropdown.init();
  });

  describe("Dropdown toggle", function(){
    describe('when click on a dropdown trigger', function () {

      it("should activate a disabled related dropdown module", function(){
        $("#dropdown-test > a:first-child").trigger("click");
        expect($("#dropdown-test").hasClass("active")).toEqual(true);
      });

      it("should disable an active related dropdown module", function() {
        $("#dropdown-test-2 > a:first-child").trigger("click");
        expect($("#dropdown-test-2").hasClass("active")).toEqual(false);
      });

    });
  });

});

describe("Dropdown: ", function(){
  beforeEach(function(){
    loadFixtures('dropdown_fixture.html');
    locastyle.dropdown.init();
  });

  describe("Dropdown toggle", function(){
    describe('when click on a dropdown trigger', function () {

      it("should activate a disabled related dropdown module", function(){
        $("#dropdown-test > a:first-child").trigger("click");
        expect($("#dropdown-test").hasClass("active")).toEqual(true);
      });

      it("should disable an active related dropdown module", function() {
        $("#dropdown-test-2 > a:first-child").trigger("click");
        expect($("#dropdown-test-2").hasClass("active")).toEqual(false);
      });

      it("should prevent default event on dropdown module", function () {
        var spyEvent = spyOnEvent('#dropdown-test > a:first-child', 'click');
        $("#dropdown-test > a:first-child").trigger("click");
        expect(spyEvent).toHaveBeenPrevented();
      });

    });
  });

});

Make sure the default event is been prevented on dropdown module click.


'use strict';

var vcap = require('../main/vcap-parser'),
    reappt = require('../main/reappt');

describe('VCAP service parser', function() {

    it('can find Reappt service', function() {
        var parser = new vcap.Parser([new reappt.Parser()]);
        var services = parser.parse({
            'push-reappt' : [{}]
        });

        expect(services.reappt).toBe(null);
    });

    it('can handle a string with the Reappt service', function() {
        var parser = new vcap.Parser([new reappt.Parser()]);
        var services = parser.parse('{"push-reappt" : [{}]}');

        expect(services.reappt).toBe(null);
    });

});

'use strict';

var vcap = require('../main/vcap-parser'),
    reappt = require('../main/reappt');

describe('VCAP service parser', function() {

    it('can find Reappt service', function() {
        var parser = new vcap.Parser([new reappt.Parser()]);
        var services = parser.parse({
            'push-reappt' : [{}]
        });

        expect(services.reappt).toBe(null);
    });

    it('can handle a string with the Reappt service', function() {
        var parser = new vcap.Parser([new reappt.Parser()]);
        var services = parser.parse('{"push-reappt":[{"credentials":{"host":"host","principal":"principal","credentials":"credentials"}}]}');

        expect(services.reappt.host).toBe("host");
        expect(services.reappt.principal).toBe("principal");
        expect(services.reappt.credentials).toBe("credentials");
    });
});

Test string parsing with a more interesting value.


var AWS = require('../core');

/**
 * Note: the `AWS.CloudSearchDomain` constructor must be created with a
 *       valid endpoint.
 */
AWS.util.update(AWS.CloudSearchDomain.prototype, {
  /**
   * @api private
   */
  validateService: function validateService() {
    if (!this.config.endpoint || this.config.endpoint.indexOf('{') >= 0) {
      var msg = 'AWS.CloudSearchDomain requires an explicit '+
                '`endpoint\' configuration option.';
      throw AWS.util.error(new Error(),
        {name: 'InvalidEndpoint', message: msg});
    }
  }
});

var AWS = require('../core');

/**
 * Constructs a service interface object. Each API operation is exposed as a
 * function on service.
 *
 * ### Sending a Request Using CloudSearchDomain
 *
 * ```javascript
 * var csd = new AWS.CloudSearchDomain({endpoint: 'my.host.tld'});
 * csd.search(params, function (err, data) {
 *   if (err) console.log(err, err.stack); // an error occurred
 *   else     console.log(data);           // successful response
 * });
 * ```
 *
 * ### Locking the API Version
 *
 * In order to ensure that the CloudSearchDomain object uses this specific API,
 * you can construct the object by passing the `apiVersion` option to the
 * constructor:
 *
 * ```javascript
 * var csd = new AWS.CloudSearchDomain({
 *   endpoint: 'my.host.tld',
 *   apiVersion: '2013-01-01'
 * });
 * ```
 *
 * You can also set the API version globally in `AWS.config.apiVersions` using
 * the **cloudsearchdomain** service identifier:
 *
 * ```javascript
 * AWS.config.apiVersions = {
 *   cloudsearchdomain: '2013-01-01',
 *   // other service API versions
 * };
 *
 * var csd = new AWS.CloudSearchDomain({endpoint: 'my.host.tld'});
 * ```
 *
 * @note You *must* provide an `endpoint` configuration parameter when
 *   constructing this service. See {constructor} for more information.
 *
 * @!method constructor(options = {})
 *   Constructs a service object. This object has one method for each
 *   API operation.
 *
 *   @example Constructing a CloudSearchDomain object
 *     var csd = new AWS.CloudSearchDomain({endpoint: 'my.host.tld'});
 *   @note You *must* provide an `endpoint` when constructing this service.
 *   @option (see AWS.Config.constructor)
 *
 * @service cloudsearchdomain
 * @version 2013-01-01
 */
AWS.util.update(AWS.CloudSearchDomain.prototype, {
  /**
   * @api private
   */
  validateService: function validateService() {
    if (!this.config.endpoint || this.config.endpoint.indexOf('{') >= 0) {
      var msg = 'AWS.CloudSearchDomain requires an explicit '+
                '`endpoint\' configuration option.';
      throw AWS.util.error(new Error(),
        {name: 'InvalidEndpoint', message: msg});
    }
  }
});

Add constructor and customized class documentation


const path = require('path')
const Module = require('module')

// Clear Node's global search paths.
Module.globalPaths.length = 0

// Clear current and parent(init.js)'s search paths.
module.paths = []
module.parent.paths = []

// Prevent Node from adding paths outside this app to search paths.
const originalNodeModulePaths = Module._nodeModulePaths
Module._nodeModulePaths = function (from) {
  const paths = originalNodeModulePaths(from)
  const rootPath = process.resourcesPath

  // If "from" is outside the app then we do nothing.
  const skipOutsidePaths = path.resolve(from).startsWith(rootPath)
  if (skipOutsidePaths) {
    return paths.filter(function (candidate) {
      return candidate.startsWith(rootPath)
    })
  }

  return paths
}

// Patch Module._resolveFilename to always require the Electron API when
// require('electron') is done.
const electronPath = path.join(__dirname, '..', process.type, 'api', 'exports', 'electron.js')
const originalResolveFilename = Module._resolveFilename
Module._resolveFilename = function (request, parent, isMain) {
  if (request === 'electron') {
    return electronPath
  } else {
    return originalResolveFilename(request, parent, isMain)
  }
}

const path = require('path')
const Module = require('module')

// Clear Node's global search paths.
Module.globalPaths.length = 0

// Clear current and parent(init.js)'s search paths.
module.paths = []
module.parent.paths = []

// Prevent Node from adding paths outside this app to search paths.
const originalNodeModulePaths = Module._nodeModulePaths
Module._nodeModulePaths = function (from) {
  const paths = originalNodeModulePaths(from)

  // If "from" is outside the app then we do nothing.
  const rootPath = process.resourcesPath + path.sep
  const fromPath = path.resolve(from) + path.sep
  const skipOutsidePaths = fromPath.startsWith(rootPath)
  if (skipOutsidePaths) {
    return paths.filter(function (candidate) {
      return candidate.startsWith(rootPath)
    })
  }

  return paths
}

// Patch Module._resolveFilename to always require the Electron API when
// require('electron') is done.
const electronPath = path.join(__dirname, '..', process.type, 'api', 'exports', 'electron.js')
const originalResolveFilename = Module._resolveFilename
Module._resolveFilename = function (request, parent, isMain) {
  if (request === 'electron') {
    return electronPath
  } else {
    return originalResolveFilename(request, parent, isMain)
  }
}

Include trailing separator in comparisons


import React from 'react';

const nbCol = 12;
const nbRow = 6;

var Widget = React.createClass({
  render: function () {
    var xSize = $(window).width() / nbCol,
      ySize = $(window).height() / nbRow;

    var style = {
      width: "calc(100vw/" + nbCol + " * " + this.props.width + ")",
      height: "calc(100vh/" + nbRow + " * " + this.props.height + ")",
    }
    if (this.props.debug == "true") {
      style.background = "tomato";
    }
    var posX = this.props.posX * xSize - xSize,
      posY = this.props.posY * ySize - ySize;

    style.transform = "translate("+ posX +"px, "+ posY +"px)";

    return (
      <div className="widget" data-x={posX} data-y={posY} style={style}>
        {this.props.render}
      </div>
    );
  }
});

export default Widget;

import React from 'react';

const nbCol = 12;
const nbRow = 6;

var Widget = React.createClass({
  render: function () {
    var xSize = $(window).width() / nbCol,
      ySize = $(window).height() / nbRow;

    var style = {
      width: "calc(100vw/" + nbCol + " * " + this.props.width + ")",
      height: "calc(100vh/" + nbRow + " * " + this.props.height + ")",
    }
    if (this.props.debug == "true") {
      style.background = "tomato";
    }
    var posX = this.props.posX * xSize - xSize,
    posY = this.props.posY * ySize - ySize,
    minX = xSize * this.props.width,
    minY = ySize * this.props.height;

    style.transform = "translate("+ posX +"px, "+ posY +"px)";

    return (
      <div className="widget" data-posx={posX} data-posy={posY} data-minx={minX} data-miny={minY} style={style}>
        {this.props.render}
      </div>
    );
  }
});

export default Widget;

Add minX and minY on widget template


/**
 * Module dependencies.
 */
var util = require('util')
  , OAuthStrategy = require("passport-oauth").OAuthStrategy;

/**
 * `Strategy` constructor.
 *
 * @api public
 */
function Strategy(options, validate) {
  options = options || {};
  options.requestTokenURL = options.requestTokenURL || 'https://twitter.com/oauth/request_token';
  options.accessTokenURL = options.accessTokenURL || 'https://twitter.com/oauth/access_token';
  options.userAuthorizationURL = options.userAuthorizationURL || 'https://twitter.com/oauth/authenticate';

  OAuthStrategy.call(this, options, validate);
  this.name = 'twitter';
}

/**
 * Inherit from `OAuthStrategy`.
 */
util.inherits(Strategy, OAuthStrategy);

/**
 * Expose `Strategy`.
 */
module.exports = Strategy;

/**
 * Module dependencies.
 */
var util = require('util')
  , OAuthStrategy = require("passport-oauth").OAuthStrategy;

/**
 * `Strategy` constructor.
 *
 * @api public
 */
function Strategy(options, verify) {
  options = options || {};
  options.requestTokenURL = options.requestTokenURL || 'https://twitter.com/oauth/request_token';
  options.accessTokenURL = options.accessTokenURL || 'https://twitter.com/oauth/access_token';
  options.userAuthorizationURL = options.userAuthorizationURL || 'https://twitter.com/oauth/authenticate';
  options.sessionKey = options.sessionKey || 'oauth:twitter';

  OAuthStrategy.call(this, options, verify);
  this.name = 'twitter';
}

/**
 * Inherit from `OAuthStrategy`.
 */
util.inherits(Strategy, OAuthStrategy);

Strategy.prototype.authenticate = function(req) {
  // When a user denies authorization on Twitter, they are presented with a link
  // to return to the application in the following format (where xxx is the
  // value of the request token):
  //
  //     http://www.example.com/auth/twitter/callback?denied=xxx
  //
  // Following the link back to the application is interpreted as an
  // authentication failure.
  if (req.query && req.query.denied) {
    return this.fail();
  }

  // Call the base class for standard OAuth authentication.
  OAuthStrategy.prototype.authenticate.call(this, req);
}

/**
 * Expose `Strategy`.
 */
module.exports = Strategy;

Support for denied Twitter authentication attempts.


"use strict";

function displayTopicsPreview(topics) {
  var message = "There are currently " + topics.length;

  _displayPreviewMessage(topics, message);
}

"use strict";

function displayTopicsPreview(topics = []) {
  let message = "There are currently " + topics.length;

  _displayPreviewMessage(topics, message);
}

Add default parameter value. Replace var -> let


var hooks = require('hooks');
var async = require('async');

function Renderable(View) {
  this.data = {};
  this.mode = 'main';
  this.view = {};

  if (typeof View === 'function') {
    this.view = new View();
  }

  this.render = function(cb) {
    // recursively render any Renderable objects inside this.data
    // this currently has one flaw, Renderable objects cannot be in nested objects,
    // or you need to render them manually
    var renders = [];
    var item;

    for (item in this.data) {
      // Intent of hasOwnProperty check is handled by constructor test.
      // noinspection JSUnfilteredForInLoop
      if (this.data[item].constructor.name === 'Renderable') {
        renders.push(function(item, next) {
          this.data[item].render(function(rendered) {
            this.data[item] = rendered;
            next(false);
          }.bind(this));
        }.bind(this, item));
      }
    }

    async.parallel(
      renders,
      function(err) {
      if (err) {
        cb(err)
      }
      else {
        this.view.data(this.data).mode(this.mode).render(cb);
      }
    }.bind(this));
  }
}

for (var k in hooks) {
  // Per hooks module documentation
  // noinspection JSUnfilteredForInLoop
  Renderable[k] = Renderable.prototype[k] = hooks[k];
}

module.exports = Renderable;

var hooks = require('hooks');
var async = require('async');

function Renderable(View) {
  this.data = {};
  this.mode = 'main';
  this.view = {};

  if (typeof View === 'function') {
    this.view = new View();
  }

  this.render = function(cb) {
    // recursively render any Renderable objects inside this.data
    // this currently has one flaw, Renderable objects cannot be in nested objects,
    // or you need to render them manually
    var renders = [];
    var item;

    for (item in this.data) {
      // Intent of hasOwnProperty check is handled by constructor test.
      // noinspection JSUnfilteredForInLoop
      if (this.data[item].constructor.name === 'Renderable') {
        //noinspection JSUnfilteredForInLoop
        renders.push(function(item, next) {
          // noinspection JSUnfilteredForInLoop
          this.data[item].render(function(rendered) {
            // noinspection JSUnfilteredForInLoop
            this.data[item] = rendered;
            next(false);
          }.bind(this));
        }.bind(this, item));
      }
    }

    async.parallel(
      renders,
      function(err) {
      if (err) {
        cb(err)
      }
      else {
        this.view.data(this.data).mode(this.mode).render(cb);
      }
    }.bind(this));
  }
}

for (var k in hooks) {
  // Per hooks module documentation
  // noinspection JSUnfilteredForInLoop
  Renderable[k] = Renderable.prototype[k] = hooks[k];
}

module.exports = Renderable;

Clean up some linter warnings


import React, {Component} from 'react'

import Icon from 'react-fa'

import {EditorState, Editor, ContentState} from 'draft-js'

export class Input extends Component{
  state = {editorState: EditorState.createWithContent(ContentState.createFromText(''))}

  componentDidMount() {
    if (this.props.isFirst) {
      // this.refs.editor.focus()
      window.thiswillwork = this.refs.editor
    }
  }

  onChange(editorState) {
    this.props.onChange(editorState.getCurrentContent().getPlainText(''))
    return this.setState({editorState})
  }

  hasValidContent() {
    const content = this.state.editorState.getCurrentContent().getPlainText('')
    return !_.isEmpty(content) && _.isEmpty(this.props.errors)
  }

  render () {
    const {name, errors} = this.props
    return (

{name}

              <Editor
                ref='editor'
                editorState={this.state.editorState}
                onChange={this.onChange.bind(this)}
                handleReturn={() => true}
              />
              {!_.isEmpty(errors) &&
<Icon name='warning' />
}

    )
  }
}

import React, {Component} from 'react'

import Icon from 'react-fa'

import {EditorState, Editor, ContentState} from 'draft-js'

export class Input extends Component{
  state = {editorState: EditorState.createWithContent(ContentState.createFromText(''))}

  componentDidMount() {
    if (this.props.isFirst) {
      setTimeout(() => {this.refs.editor.focus()}, 1)
    }
  }

  onChange(editorState) {
    this.props.onChange(editorState.getCurrentContent().getPlainText(''))
    return this.setState({editorState})
  }

  hasValidContent() {
    const content = this.state.editorState.getCurrentContent().getPlainText('')
    return !_.isEmpty(content) && _.isEmpty(this.props.errors)
  }

  render () {
    const {name, errors} = this.props
    return (

{name}

              <Editor
                ref='editor'
                editorState={this.state.editorState}
                onChange={this.onChange.bind(this)}
                handleReturn={() => true}
              />
              {!_.isEmpty(errors) &&
<Icon name='warning' />
}

    )
  }
}

Add delay to field focus to ensure it will work


'use strict'

var parent = require('aedes-persistence/abstract')

module.exports = parent

'use strict'

var parent = require('../aedes-persistence/abstract')

module.exports = parent

Fix tests for aedes-persistence mongodb


import { configure, addDecorator } from '@storybook/react';
import { setOptions } from '@storybook/addon-options';
import '../lib/global.css';

/**
 * React intl support
 */

// Load the locale data for all your defined locales
import { setIntlConfig, withIntl } from 'storybook-addon-intl';
import enTranslations from '../translations/en.json';
import { addLocaleData } from 'react-intl';
import enLocaleData from 'react-intl/locale-data/en';
addLocaleData(enLocaleData);

// Define messages
const messages = {
  en: enTranslations,
};

// Set intl configuration
setIntlConfig({
    locales: ['en'],
    defaultLocale: 'en',
    getMessages: (locale) => messages[locale]
});

addDecorator(withIntl);

/**
 * Set options
 */
setOptions({
  name: 'FOLIO Stripes',
});

const req = require.context('../lib', true, /\.stories\.js$/);

function loadStories() {
  req.keys().forEach((filename) => req(filename));
}

configure(loadStories, module);

import { configure, addDecorator } from '@storybook/react';
import { setOptions } from '@storybook/addon-options';
import '../lib/global.css';

/**
 * React intl support
 */

// Load the locale data for all your defined locales
import { setIntlConfig, withIntl } from 'storybook-addon-intl';
import enTranslations from '../translations/stripes-components/en.json';
import { addLocaleData } from 'react-intl';
import enLocaleData from 'react-intl/locale-data/en';
addLocaleData(enLocaleData);

// Define messages
const messages = {
  en: enTranslations,
};

// Set intl configuration
setIntlConfig({
    locales: ['en'],
    defaultLocale: 'en',
    getMessages: (locale) => messages[locale]
});

addDecorator(withIntl);

/**
 * Set options
 */
setOptions({
  name: 'FOLIO Stripes',
});

const req = require.context('../lib', true, /\.stories\.js$/);

function loadStories() {
  req.keys().forEach((filename) => req(filename));
}

configure(loadStories, module);

Fix translations path for storybook


// Twitter Sample
//
// Using the Twitter Streaming API. In this example, we retrieve the
// sample of the statuses in real time.

// Import node modules
var Twit   = require('twit'),           // Twitter API Client
    config = require('./config.json');  // Twitter Credentials

// Configure the Twit object with the application credentials
var T = new Twit(config);

// Subscribe to the stream sample, for tweets in english
var stream = T.stream('statuses/sample');

// The callback will be invoked on each tweet. Here, we print the username
// and the text of the tweet in the screen.
stream.on('tweet', function(tweet) {
    console.log('[@' + tweet.user.screen_name + ']: ' + tweet.text);
});

// The 'connect' callback is invoked when the Twitter API Client
// tries to connect to Twitter.
stream.on('connect', function(msg) {
    console.log('connect');
});

// The 'connected' event is triggered when the connection is successful.
stream.on('connected', function(msg) {
    console.log('connected');
});

// The 'warning' event is triggered if the client is not processing the
// tweets fast enough.
stream.on('warning', function(msg) {
    console.warning('warning')
});

// The 'disconnect' event is triggered when a disconnect message comes from
// Twitter.
stream.on('disconnect', function(msg) {
    console.log('disconnect');
});

// Twitter Sample
//
// Using the Twitter Streaming API. In this example, we retrieve the
// sample of the statuses in real time.

// Import node modules
var Twit   = require('twit'),           // Twitter API Client
    config = require('./config.json');  // Twitter Credentials

// Configure the Twit object with the application credentials
var T = new Twit(config);

// Subscribe to the sample stream and begin listening
var stream = T.stream('statuses/sample');

// The callback will be invoked on each tweet. Here, we print the username
// and the text of the tweet in the screen.
stream.on('tweet', function(tweet) {
    console.log('[@' + tweet.user.screen_name + ']: ' + tweet.text);
});

// The 'connect' callback is invoked when the Twitter API Client
// tries to connect to Twitter.
stream.on('connect', function(msg) {
    console.log('connect');
});

// The 'connected' event is triggered when the connection is successful.
stream.on('connected', function(msg) {
    console.log('connected');
});

// The 'reconnect' event is triggered when a reconnection is scheduled.
stream.on('reconnect', function(req, res, interval) {
    console.log('Reconnecting in ' + (interval / 3) + ' seconds.');
});

// The 'warning' event is triggered if the client is not processing the
// tweets fast enough.
stream.on('warning', function(msg) {
    console.warning('warning')
});

// The 'disconnect' event is triggered when a disconnect message comes from
// Twitter.
stream.on('disconnect', function(msg) {
    console.log('disconnect');
});

Update the twitter sample example


const {schema: baseSchema} = require("prosemirror-schema-basic");
const model = require("prosemirror-model"),
      Schema = model.Schema,
      Mark = model.Mark,
      MarkType = model.MarkType,
      Attribute = model.Attribute,
      Fragment = model.Fragment;
const {addListNodes} = require("prosemirror-schema-list");

const chapterMarkSpec = baseSchema.spec.marks.append({mention: {
    attrs: {
        mentionTargets: {default: []}
    },
    parseDOM: [{tag: "span[data-mentions]", getAttrs(dom) {
        return {mentionTargets: JSON.parse(dom.getAttribute("data-mentions"))};
    }}],
    toDOM(node) {
        const targets = node.attrs.mentionTargets;

        return [
            "span",
            {"data-mentions": JSON.stringify(targets),
             "class": "mention" + targets.map(t => ` mention-${t.id % 5 + 1}`).join(""),
             "title": "Only for " + targets.map(t => t.name).join(", ")
            }
        ];
    }
}});

const chapterSchema = new Schema({
  nodes: addListNodes(baseSchema.spec.nodes, "paragraph block*", "block"),
  marks: chapterMarkSpec
});

const descriptionSchema = new Schema({
  nodes: addListNodes(baseSchema.spec.nodes, "paragraph block*", "block"),
  marks: baseSchema.spec.marks
});

module.exports.chapter = chapterSchema;
module.exports.description = descriptionSchema;

const {schema: baseSchema} = require("prosemirror-schema-basic");
const model = require("prosemirror-model"),
      Schema = model.Schema,
      Mark = model.Mark,
      MarkType = model.MarkType,
      Attribute = model.Attribute,
      Fragment = model.Fragment;
const {addListNodes} = require("prosemirror-schema-list");

const chapterMarkSpec = baseSchema.spec.marks.append({mention: {
    attrs: {
        mentionTargets: {default: []}
    },
    parseDOM: [{tag: "span[data-mentions]", getAttrs(dom) {
        return {mentionTargets: JSON.parse(dom.getAttribute("data-mentions"))};
    }}],
    toDOM(node) {
        const targets = node.attrs.mentionTargets;

        return [
            "span",
            {"data-mentions": JSON.stringify(targets),
             "class": "mention" + targets.map(t => ` mention-${t.id % 5 + 1}`).join(""),
             "title": "Only for " + targets.map(t => t.name).join(", ")
            }
        ];
    }
}});

const nodeSpecWithLists = addListNodes(baseSchema.spec.nodes,
                                       "paragraph block*",
                                       "block");
const chapterSchema = new Schema({
  nodes: nodeSpecWithLists,
  marks: chapterMarkSpec
});

const descriptionSchema = new Schema({
  nodes: nodeSpecWithLists.remove("image"),
  marks: baseSchema.spec.marks
});

module.exports.chapter = chapterSchema;
module.exports.description = descriptionSchema;

Remove images from the character description schema


function log(method, level, input) {
  const args = [level].concat([].slice.call(input));
  console[method].apply(console, args); // eslint-disable-line no-console
}

export const None  = 0;
export const Error = 1;
export const Warn  = 2;
export const Info  = 3;
export const Debug = 4;

export default function(_, method) {
  let level = _ || None;
  return {
    level(_) {
      if (arguments.length) {
        level = +_;
        return this;
      } else {
        return level;
      }
    },
    error() {
      if (level >= Error) log(method || 'error', 'ERROR', arguments);
      return this;
    },
    warn() {
      if (level >= Warn) log(method || 'warn', 'WARN', arguments);
      return this;
    },
    info() {
      if (level >= Info) log(method || 'log', 'INFO', arguments);
      return this;
    },
    debug() {
      if (level >= Debug) log(method || 'log', 'DEBUG', arguments);
      return this;
    }
  };
}

function log(method, level, input) {
  const args = [level].concat([].slice.call(input));
  console[method].apply(console, args); // eslint-disable-line no-console
}

export const None  = 0;
export const Error = 1;
export const Warn  = 2;
export const Info  = 3;
export const Debug = 4;

export default function(_, method, handler) {
  let level = _ || None;
  let handler = handler || log;
  return {
    level(_) {
      if (arguments.length) {
        level = +_;
        return this;
      } else {
        return level;
      }
    },
    error() {
      if (level >= Error) handler(method || 'error', 'ERROR', arguments);
      return this;
    },
    warn() {
      if (level >= Warn) handler(method || 'warn', 'WARN', arguments);
      return this;
    },
    info() {
      if (level >= Info) handler(method || 'log', 'INFO', arguments);
      return this;
    },
    debug() {
      if (level >= Debug) handler(method || 'log', 'DEBUG', arguments);
      return this;
    }
  };
}

Allow a custom log handler as optional parameter


let util = require("../util");

let input = require("fs").readFileSync("./data").toString();

let presentDimensions = input
	.split("\n")
	.map(present =>
		present.split("x")
		.map(dimension => parseInt(dimension, 10))
		.sort((a, b) => a - b)
	)
	.map(present => {
		return {
			l: present[0],
			w: present[1],
			h: present[2]
		};
	});

let wrappingNeeded = util.sum(presentDimensions.map(present =>
	present.l * present.w + // Area of smallest side
	2 * present.l * present.w +
	2 * present.w * present.h +
	2 * present.h * present.l
));

console.log("Sq. Ft. Wrapping Paper Needed:", wrappingNeeded);

let ribbonNeeded = util.sum(presentDimensions.map(present =>
	2 * present.l + 2 * present.w + // perimeter of smallest face, ribbon wrap
	present.l * present.w * present.h // cubic area, bow
));

console.log("Ft. Ribbon Needed:", ribbonNeeded);

let util = require("../util");

let input = require("fs").readFileSync("./data").toString();

let presentDimensions = input
	.split("\n")
	.map(present =>
		present.split("x")
			.map(dimension => parseInt(dimension, 10))
			.sort((a, b) => a - b)
	);

let wrappingNeeded = util.sum(presentDimensions.map(present =>
	present[0] * present[1] + // Area of smallest side
	2 * present[0] * present[1] +
	2 * present[1] * present[2] +
	2 * present[2] * present[0]
));

console.log("Sq. Ft. Wrapping Paper Needed:", wrappingNeeded);

let ribbonNeeded = util.sum(presentDimensions.map(present =>
	2 * present[0] + 2 * present[1] + // perimeter of smallest face, ribbon wrap
	present[0] * present[1] * present[2] // cubic area, bow
));

console.log("Ft. Ribbon Needed:", ribbonNeeded);

Remove mapping of arbitrary lengths to l/w/h.


import React from "react";
import ReactDOM from "react-dom";

import tabify from "../../utils/tabify";
import * as d3 from "d3";
import "./BarGraph.css";

export default class BarGraph extends React.Component {
    render() {

        const { response, configuration, onBarClick } = this.props;
        const { width, height } = this.props;

        if (!response || response.error)
            return;

        const data = tabify(response.results);
        const properties = configuration.data;

        return (
            <div className="bar-graph">
                <svg width={width} height={height}>
                    {data.map((d, i) => (
                        <rect
                            x={i*50}
                            y="0"
                            width="40"
                            height="40"
                        />
                    ))}
                </svg>
            </div>
        );
    }
}

BarGraph.propTypes = {
  configuration: React.PropTypes.object,
  response: React.PropTypes.object
};

import React from "react";
import ReactDOM from "react-dom";

import tabify from "../../utils/tabify";
import * as d3 from "d3";
import "./BarGraph.css";

export default class BarGraph extends React.Component {
    constructor(){
        super();
        this.xScale = d3.scaleBand();
        this.yScale = d3.scaleLinear();
    }
    render() {

        const {
          xScale,
          yScale,
          props: {
            response,
            configuration,
            onBarClick,
            width,
            height
          }
        } = this;

        if (!response || response.error)
            return;

        const data = tabify(response.results);
        const properties = configuration.data;
        const { xColumn, yColumn } = properties;

        xScale
          .domain(data.map(function (d){ return d[xColumn]; }))
          .range([0, width]);

        yScale
          .domain([0, d3.max(data, function (d){ return d[yColumn] })])
          .range([height, 0]);

        console.log(xScale.domain())
        console.log(xScale.range())

        return (
            <div className="bar-graph">
                <svg width={width} height={height}>
                    {data.map((d, i) => (
                        <rect
                            key={ i }
                            x={ xScale(d[xColumn]) }
                            y={ yScale(d[yColumn]) }
                            width={ xScale.bandwidth() }
                            height={ height - yScale(d[yColumn]) }
                        />
                    ))}
                </svg>
            </div>
        );
    }
}

BarGraph.propTypes = {
  configuration: React.PropTypes.object,
  response: React.PropTypes.object
};

Add pseudo bar chart using D3 scales with JSX


import React from 'react'
import styled from 'styled-components'

const isActualThumbnail = thumbnail => thumbnail.startsWith('http')
const getPlaceholder = str => {
  if (['nsfw'].includes(str)) {
    return str
  } else {
    return 's'
  }
}

const BaseThumbnail = styled.div`
  width: 70px;
  height: 70px;
  border-radius: 4px;
  overflow: hidden;
`

const Image = BaseThumbnail.extend`
  background: url(${props => props.thumbnail});
  background-size: cover;
`

const Letter = BaseThumbnail.extend`
  display: flex;
  align-items: center;
  justify-content: center;
  background: #323a45;
  color: #fff;
  text-transform: uppercase;
  font-size: 24px;
`

const Thumbnail = props => {
  if (isActualThumbnail(props.thumbnail)) {
    return <Image {...props} />
  }

  return <Letter>{getPlaceholder(props.thumbnail)}</Letter>
}

export default Thumbnail

import React from 'react'
import styled from 'styled-components'

const isActualThumbnail = thumbnail => thumbnail.startsWith('http')
const getPlaceholder = str => {
  if (['nsfw'].includes(str)) {
    return str
  } else {
    return 'self'
  }
}

const BaseThumbnail = styled.div`
  width: 70px;
  height: 70px;
  border-radius: 4px;
  overflow: hidden;
`

const Image = BaseThumbnail.extend`
  background: url(${props => props.thumbnail});
  background-size: cover;
`

const Letter = BaseThumbnail.extend`
  display: flex;
  align-items: center;
  justify-content: center;
  background: #323a45;
  color: #fff;
  text-transform: uppercase;
  font-size: 20px;
`

const Thumbnail = props => {
  if (isActualThumbnail(props.thumbnail)) {
    return <Image {...props} />
  }

  return <Letter>{getPlaceholder(props.thumbnail)}</Letter>
}

export default Thumbnail

Change thumbnail to display self


/* eslint-disable no-unused-vars */
import React from 'react';
/* eslint-enable no-unused-vars */

import General from './service-schema/General';
import Labels from './service-schema/Labels';
import Optional from './service-schema/Optional';
import ContainerSettings from './service-schema/ContainerSettings';

let ServiceSchema = {
  type: 'object',
  properties: {
    general: General,
    containerSettings: ContainerSettings,
    optional: Optional,
    labels: Labels
  },
  required: [
    'general'
  ]
};

module.exports = ServiceSchema;

/* eslint-disable no-unused-vars */
import React from 'react';
/* eslint-enable no-unused-vars */

import ContainerSettings from './service-schema/ContainerSettings';
import General from './service-schema/General';
import Labels from './service-schema/Labels';
import Optional from './service-schema/Optional';

let ServiceSchema = {
  type: 'object',
  properties: {
    general: General,
    containerSettings: ContainerSettings,
    optional: Optional,
    labels: Labels
  },
  required: [
    'general'
  ]
};

module.exports = ServiceSchema;

Change order of the imports to be alphabetised


<% if (framework === 'angular2') { -%>
require('reflect-metadata');
<% } -%>

/* globals require */
<% if (js === 'babel') { -%>
const context = require.context('./app', true, /\.spec$/);
<% } else { -%>
var context = require.context('./app', true, /\.spec$/);
<% } -%>
context.keys().forEach(context);

<% if (framework === 'angular2') { -%>
require('reflect-metadata');
<% } -%>

/* globals require */
<% if (js === 'js') { -%>
var context = require.context('./app', true, /\.spec$/);
<% } else { -%>
const context = require.context('./app', true, /\.spec$/);
<% } -%>
context.keys().forEach(context);

Use const instead of var for typescript


import { connect } from 'react-redux'
import DatasetOverview from '../components/DatasetOverview'
import { makeDatasetFactDictFxn, makeColTypesCntFxn, makePublishingFactsFxn, calculatePublishingHealthFxn } from '../reducers'
import { loadRelatedDatasets } from '../actions'

const mapStateToProps = (state, ownProps) => {
  const { metadata } = state
  metadata.datasetFacts = makeDatasetFactDictFxn(state)
  metadata.colCounts = makeColTypesCntFxn(state)
  metadata.publishingFacts = makePublishingFactsFxn(state)
  metadata.publishing_health = calculatePublishingHealthFxn(state)
  metadata.publishing_faqs = makePublishingFactsFxn(state)
  if (state.routing.locationBeforeTransitions.pathname) {
    let route = state.routing.locationBeforeTransitions.pathname.split("/")
    metadata.fbf = route[route.length-1]
  }
  return {
    metadata
  }
}

const mapDispatchToProps = (dispatch, ownProps) => {
  return {
    loadRelatedDatasets: (fbf) => {
      return dispatch(loadRelatedDatasets(fbf))
    }
  }
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(DatasetOverview)

import { connect } from 'react-redux'
import DatasetOverview from '../components/DatasetOverview'
import { makeDatasetFactDictFxn, makeColTypesCntFxn, makePublishingFactsFxn, calculatePublishingHealthFxn } from '../reducers'
import { loadRelatedDatasets } from '../actions'

const mapStateToProps = (state, ownProps) => {
  const { metadata } = state
  return {
    metadata,
    datasetFacts: makeDatasetFactDictFxn(state),
    colCounts: makeColTypesCntFxn(state),
    publishingFacts: makePublishingFactsFxn(state),
    publishing_health: calculatePublishingHealthFxn(state),
    publishing_faqs: makePublishingFactsFxn(state)
  }
}

const mapDispatchToProps = (dispatch, ownProps) => {
  return {
    loadRelatedDatasets: (fbf) => {
      return dispatch(loadRelatedDatasets(fbf))
    }
  }
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(DatasetOverview)

Refactor overview so props do not mutate state in container


// Catalan

jQuery.extend( jQuery.fn.pickadate.defaults, {
    monthsFull: [ 'Gener', 'Febrer', 'Març', 'Abril', 'Maig', 'juny', 'Juliol', 'Agost', 'Setembre', 'Octubre', 'Novembre', 'Desembre' ],
    monthsShort: [ 'Gen', 'Feb', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Oct', 'Nov', 'Des' ],
    weekdaysFull: [ 'diumenge', 'dilluns', 'dimarts', 'dimecres', 'dijous', 'divendres', 'dissabte' ],
    weekdaysShort: [ 'diu', 'dil', 'dim', 'dmc', 'dij', 'div', 'dis' ],
    today: 'avui',
    clear: 'esborrar',
    close: 'tancar',
    firstDay: 1,
    format: 'dddd d !de mmmm !de yyyy',
    formatSubmit: 'yyyy/mm/dd'
});

jQuery.extend( jQuery.fn.pickatime.defaults, {
    clear: 'esborrar'
});

// Catalan

jQuery.extend( jQuery.fn.pickadate.defaults, {
    monthsFull: [ 'Gener', 'Febrer', 'Març', 'Abril', 'Maig', 'juny', 'Juliol', 'Agost', 'Setembre', 'Octubre', 'Novembre', 'Desembre' ],
    monthsShort: [ 'Gen', 'Feb', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Oct', 'Nov', 'Des' ],
    weekdaysFull: [ 'diumenge', 'dilluns', 'dimarts', 'dimecres', 'dijous', 'divendres', 'dissabte' ],
    weekdaysShort: [ 'diu', 'dil', 'dim', 'dmc', 'dij', 'div', 'dis' ],
    today: 'avui',
    clear: 'esborra',
    close: 'tanca',
    firstDay: 1,
    format: 'dddd d !de mmmm !de yyyy',
    formatSubmit: 'yyyy/mm/dd'
});

jQuery.extend( jQuery.fn.pickatime.defaults, {
    clear: 'esborra'
});

Correct Catalan verbs according to the Style Guide


/**
 * @module 1-liners/pipeAll
 *
 * @description
 *
 * Pipe arguments through an array of functions.
 *
 * @example
 *
 * 	const pipeAll = require('1-liners/pipeAll');
 *
 * 	pipeAll([f, g, h])(1, 2) === h(g(f(1, 2)));
 *
 */
export default (fns) => fns.reverse().reduce( (f, g) => (...args) => f(g(...args)) );

/**
 * @module 1-liners/pipeAll
 *
 * @description
 *
 * Pipe arguments through an array of functions.
 *
 * @example
 *
 * 	const pipeAll = require('1-liners/pipeAll');
 *
 * 	pipeAll([f, g, h])(1, 2) === h(g(f(1, 2)));
 *
 */
export default (fns) => fns.reduceRight( (f, g) => (...args) => f(g(...args)) );

Use `.reduceRight` instead of `.reverse().reduce`


/* eslint-env es6 */
/* global VertexIndices */
window.lerpBoxVertex = (function() {
  'use strict';

  return function lerpA( geometryA, vertexA ) {
    const indexA = VertexIndices[ vertexA.toUpperCase() ];

    return function lerpB( geometryB, vertexB ) {
      const indexB = VertexIndices[ vertexB.toUpperCase() ];

      return function lerp( t ) {
        geometryA.vertices[ indexA ].lerp( geometryB.vertices[ indexB ], t );
        return geometryA;
      };
    };
  };
}());

/* eslint-env es6 */
/* global VertexIndices */
window.lerpBoxVertex = (function() {
  'use strict';

  return function lerpA( vertexA, t ) {
    const indexA = VertexIndices[ vertexA.toUpperCase() ];

    return function lerpB( geometryA, geometryB, vertexB ) {
      const indexB = VertexIndices[ vertexB.toUpperCase() ];
      geometryA.vertices[ indexA ].lerp( geometryB.vertices[ indexB ], t );
      return geometryA;
    };
  };
}());

Change argument order of BoxGeometry lerp().


const TABLE_NAME = 'users';

exports.up = function(knex, Promise) {

  return Promise.all([
    knex.schema.table(TABLE_NAME, function (table) {
      table.dropColumn('login');
      table.boolean('cgu');
      table.unique('email');
    })
  ]);

};

exports.down = function(knex, Promise) {
  return Promise.all([
    knex.schema.table(TABLE_NAME, function (table) {
      table.string('login').defaultTo("").notNullable();
      table.dropColumn('cgu');
    })
  ]);
};

const TABLE_NAME = 'users';

exports.up = function(knex, Promise) {

  return Promise.all([
    knex.schema.table(TABLE_NAME, function (table) {
      table.dropColumn('login');
      table.boolean('cgu');
    })
  ]);

};

exports.down = function(knex, Promise) {
  return Promise.all([
    knex.schema.table(TABLE_NAME, function (table) {
      table.string('login').defaultTo("").notNullable();
      table.dropColumn('cgu');
    })
  ]);
};

FIX - Removing unique constraint on user.email from migration script


const postcss = require('postcss')
const _ = require('lodash')

function findColor(colors, color) {
  return _.mapKeys(colors, (value, key) => {
    return _.camelCase(key)
  })[_.camelCase(color)]
}

module.exports = function ({ colors, backgroundColors }) {
  if (_.isArray(backgroundColors)) {
    backgroundColors = _(backgroundColors).map(color => [color, color]).fromPairs()
  }

  return _(backgroundColors).toPairs().map(([className, colorName]) => {
    const kebabClass = _.kebabCase(className)

    return postcss.rule({
      selector: `.bg-${kebabClass}`
    }).append({
      prop: 'background-color',
      value: findColor(colors, colorName)
    })
  }).value()
}

const postcss = require('postcss')
const _ = require('lodash')

function findColor(colors, color) {
  const colorsNormalized = _.mapKeys(colors, (value, key) => {
    return _.camelCase(key)
  })

  return _.get(colorsNormalized, _.camelCase(color), color)
}

module.exports = function ({ colors, backgroundColors }) {
  if (_.isArray(backgroundColors)) {
    backgroundColors = _(backgroundColors).map(color => [color, color]).fromPairs()
  }

  return _(backgroundColors).toPairs().map(([className, colorName]) => {
    const kebabClass = _.kebabCase(className)

    return postcss.rule({
      selector: `.bg-${kebabClass}`
    }).append({
      prop: 'background-color',
      value: findColor(colors, colorName)
    })
  }).value()
}

Support colors not in map


'use strict';

/*
 * Helper functions.
 *
 * This script contains miscellaneous helpers used throughout Tanura's code.
 */

/*
 * Log something.
 *
 * For now, this is just aliased to console.log.
 */
tanura.log = console.log;

'use strict';

/*
 * Helper functions.
 *
 * This script contains miscellaneous helpers used throughout Tanura's code.
 */

/*
 * Log something.
 */
tanura.log = (_) => console.log("[Tanura] " + _);

Add [Tanura] badge to log messages.


define([
  'summernote/base/core/func',
  'summernote/base/core/list',
  'summernote/base/core/dom'
], function (func, list, dom) {
  var ImagePopover = function (context) {
    var ui = $.summernote.ui;

    var options = context.options;

    this.shouldInitialize = function () {
      return !list.isEmpty(options.popover.image);
    };

    this.initialize = function () {
      this.$popover = ui.popover({
        className: 'note-image-popover'
      }).render().appendTo('body');
      var $content = this.$popover.find('.popover-content');

      context.invoke('buttons.build', $content, options.popover.image);
    };

    this.destroy = function () {
      this.$popover.remove();
    };

    this.update = function (target) {
      if (dom.isImg(target)) {
        var pos = dom.posFromPlaceholder(target);
        this.$popover.css({
          display: 'block',
          left: pos.left,
          top: pos.top
        });
      } else {
        this.hide();
      }
    };

    this.hide = function () {
      this.$popover.hide();
    };
  };

  return ImagePopover;
});

define([
  'summernote/base/core/func',
  'summernote/base/core/list',
  'summernote/base/core/dom',
  'summernote/base/core/key'
], function (func, list, dom, key) {
  var ImagePopover = function (context) {
    var self = this;
    var ui = $.summernote.ui;

    var options = context.options;

    this.shouldInitialize = function () {
      return !list.isEmpty(options.popover.image);
    };

    this.events = {
      'summernote.keydown': function (we, e) {
        self.handleKeydown(e);
      }
    };

    this.initialize = function () {
      this.$popover = ui.popover({
        className: 'note-image-popover'
      }).render().appendTo('body');
      var $content = this.$popover.find('.popover-content');

      context.invoke('buttons.build', $content, options.popover.image);
    };

    this.destroy = function () {
      this.$popover.remove();
    };

    this.isVisible = function() {
      return this.$popover.is(':visible');
    };

    this.update = function (target) {
      if (dom.isImg(target)) {
        var pos = dom.posFromPlaceholder(target);
        this.$popover.css({
          display: 'block',
          left: pos.left,
          top: pos.top
        });

        //be sure editor has focus to handle key events
        context.invoke('editor.focus');
      } else {
        this.hide();
      }
    };

    this.hide = function () {
      this.$popover.hide();
    };

    this.handleKeydown = function(e) {
      if (list.contains([key.code.BACKSPACE], e.keyCode)) {
        if (this.isVisible()) {
          context.invoke('editor.removeMedia');
        }
      }
    };
  };

  return ImagePopover;
});

Remove image on backspace key event


/*! @license ©2013 Ruben Verborgh - Multimedia Lab / iMinds / Ghent University */

/** A TtsDatasource fetches triples from a Triple File System */

var tfs = require('triple-file-system'),
    q = require('q');

var LIMIT = 100;

// Creates a new TfsDatasource
function TfsDatasource(path) {
  this._tfs = new tfs.TripleFileSystem(path);
  this._metadataReader = new tfs.TripleFileSystemMetadataReader(this._tfs);
}

TfsDatasource.prototype = {
  // Get triples that match the given pattern
  query: function (pattern) {
    // Read the triples
    var triples = [], triplesDeferred = q.defer(),
        reader = new tfs.TripleFileSystemReader(this._tfs, pattern);
    reader.on('data', function (triple) {
      triples.push(triple);
      if (triples.length >= LIMIT) {
        reader.pause();
        triplesDeferred.resolve(triples);
      }
    });
    reader.on('end',  function () { triplesDeferred.resolve(triples); });

    // Return the triples and the count
    return q.spread([triplesDeferred.promise, this._metadataReader.count(pattern)],
                    function (triples, count) { return { triples: triples, total: count }; });
  },
};

module.exports = TfsDatasource;

/*! @license ©2013 Ruben Verborgh - Multimedia Lab / iMinds / Ghent University */

/** A TtsDatasource fetches triples from a Triple File System */

var tfs = require('triple-file-system'),
    q = require('q');

var LIMIT = 100;
var LARGECOUNTESTIMATE = 500000000;

// Creates a new TfsDatasource
function TfsDatasource(path) {
  this._tfs = new tfs.TripleFileSystem(path);
  this._metadataReader = new tfs.TripleFileSystemMetadataReader(this._tfs);
}

TfsDatasource.prototype = {
  // Get triples that match the given pattern
  query: function (pattern) {
    // Read the triples
    var triples = [], triplesDeferred = q.defer(),
        reader = new tfs.TripleFileSystemReader(this._tfs, pattern);
    reader.on('data', function (triple) {
      triples.push(triple);
      if (triples.length >= LIMIT) {
        reader.pause();
        triplesDeferred.resolve(triples);
      }
    });
    reader.on('end',  function () { triplesDeferred.resolve(triples); });

    // Get the total count, returning an estimate if counting takes too long
    var count = q.timeout(this._metadataReader.count(pattern), 500)
                 .then(null, function () { return LARGECOUNTESTIMATE; });

    // Return the triples and the count
    return q.spread([triplesDeferred.promise, count],
                    function (triples, count) { return { triples: triples, total: count }; });
  },
};

module.exports = TfsDatasource;

Return an estimate if counting takes too long.


// In this file you can configure migrate-mongo

module.exports = {
  mongodb: {
    // TODO Change (or review) the url to your MongoDB:
    url: "mongodb://localhost:27017",

    // TODO Change this to your database name:
    databaseName: "YOURDATABASENAME",

    options: {
      useNewUrlParser: true // removes a deprecation warning when connecting
      //   connectTimeoutMS: 3600000, // increase connection timeout to 1 hour
      //   socketTimeoutMS: 3600000, // increase socket timeout to 1 hour
    }
  },

  // The migrations dir, can be an relative or absolute path. Only edit this when really necessary.
  migrationsDir: "migrations",

  // The mongodb collection where the applied changes are stored. Only edit this when really necessary.
  changelogCollectionName: "changelog"
};

// In this file you can configure migrate-mongo

const config = {
  mongodb: {
    // TODO Change (or review) the url to your MongoDB:
    url: "mongodb://localhost:27017",

    // TODO Change this to your database name:
    databaseName: "YOURDATABASENAME",

    options: {
      useNewUrlParser: true // removes a deprecation warning when connecting
      //   connectTimeoutMS: 3600000, // increase connection timeout to 1 hour
      //   socketTimeoutMS: 3600000, // increase socket timeout to 1 hour
    }
  },

  // The migrations dir, can be an relative or absolute path. Only edit this when really necessary.
  migrationsDir: "migrations",

  // The mongodb collection where the applied changes are stored. Only edit this when really necessary.
  changelogCollectionName: "changelog"
};

module.exports = Promise.resolve(config);

Return a promise in the templated migrate-mongo


/**
 * Created by Stein-Otto Svorstøl on 26.08.15.
 */
'use strict';

var bookController = require('./controllers/bookController');

function setup(app){
    var bodyParser = require('body-parser'); // Some setup for encoding of requests
    app.use(bodyParser.json());       // to support JSON-encoded bodies
    app.use(bodyParser.urlencoded({     // to support URL-encoded bodies
        extended: true
    }));

    app.use(function(req, res, next) { // Headers to allow CORS and different requests
        res.header("Access-Control-Allow-Origin", "*");
        res.header('Access-Control-Allow-Methods', 'OPTIONS, GET, PUT');
        res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        next();
    });

    app.put('/book', bookController.createNew);
    app.get('/book/:isbn', bookController.getWithISBN);
    app.get('/book/:isbn/:owner', bookController.getWithISBNAndOwner);

}

exports.setup = setup;

/**
 * Created by Stein-Otto Svorstøl on 26.08.15.
 */
'use strict';

var bookController = require('./controllers/bookController');

function setup(app){
    var bodyParser = require('body-parser'); // Some setup for encoding of requests
    app.use(bodyParser.json());       // to support JSON-encoded bodies
    app.use(bodyParser.urlencoded({     // to support URL-encoded bodies
        extended: true
    }));

    app.use(function(req, res, next) { // Headers to allow CORS and different requests
        res.header("Access-Control-Allow-Origin", "*");
        res.header('Access-Control-Allow-Methods', 'OPTIONS, GET, PUT');
        res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        next();
    });

    app.put('/api/book', bookController.createNew);
    app.get('/api/book/:isbn', bookController.getWithISBN);
    app.get('/api/book/:isbn/:owner', bookController.getWithISBNAndOwner);

}

exports.setup = setup;

Add /api/ in front of API-URLs


var config = require('./config.js');
var Slack = require('slack-client');
var token = config.slackApiKey;
var slack = new Slack(token, true, true);

slack.on('message', function(message) {
    var user = slack.getUserByID(message.user);
 	var channel = slack.getChannelGroupOrDMByID(message.channel);

    if (message.type === 'message'
    	&& channel.name === 'bottesting') {
        console.log(channel.name + ' ' + user.name + ':' + message.text);
    	channel.send('Hey there');
    }
});

slack.login();

var config = require('./config.js');
var Slack = require('slack-client');
var token = config.slackApiKey;
var slack = new Slack(token, true, true);

slack.on('message', function(message) {
    var user = slack.getUserByID(message.user);
    var channel = slack.getChannelGroupOrDMByID(message.channel);

    // if (message.type === 'message'
    //     && channel.name === 'bottesting') {
    //     console.log(channel.name + ' ' + user.name + ':' + message.text);
    //     channel.send('Hey there');
    // }

    var regex = /([0-9]{1,2}):([0-9]{2})(am|pm)?/gi;

    var match = regex.exec(message);

    console.log(match);

    if(match && message.type === 'message' && channel.name === 'bottesting') {

        var time = new Date();

        var hour = parseInt(match[1], 10);
        var mins = parseInt(match[2], 10);

        if(match[3] && match[3].toLowerCase() === 'pm') {
            hour = hour + 12;
        }

        time.setHours(hour);
        time.setMinutes(mins);

        channel.send(time);

        // User.findOne({uuid: message.user}, function(err, user) {

        //     if(err) {
        //         return;
        //     }

        //     if(!user.timezone) {
        //         // ask user for timezone
        //         return;
        //     }

        //     channel.users.forEach(function (user) {

        //         User.findOne({uuid: user.id}, function(err, user) {

        //             if(!err && user.timezone) {
        //                 channel.sendDM(time, user.id);
        //             }

        //         });

        //     });

        // });

    }
});

slack.login();

Create basic time regex and stub out flow


'use strict';

// http://stackoverflow.com/a/872537
function getScrollTop(){
  if ( typeof window.pageYOffset !== 'undefined' ) {
    // most browsers except IE before #9
    return window.pageYOffset;
  } else {
    var b = document.body; // IE 'quirks'
    var d = document.documentElement; // IE with doctype
    return ((d.clientHeight) ? d : b).scrollTop;
  }
}

module.exports = [
  '$rootScope', '$window', '$timeout',
  function BroadcastScrollPositionDirective($rootScope, $window, $timeout) {
    return {
      restrict: 'A',
      link: function($scope, $el, attrs) {
        var el = attrs.assBroadcastScrollPosition ? eval(attrs.assBroadcastScrollPosition) : document.body;
        $rootScope.assBroadcastScrollPosition = 0;
        var p = $timeout();
        function updateScope() {
          $timeout.cancel(p);
          p = $timeout(function(){
            $rootScope.$apply(function(){
              $rootScope.assBroadcastScrollPosition = getScrollTop() - el.offsetHeight + window.innerHeight*2.5;
            });
          });
        }
        $window.addEventListener('scroll', updateScope);
        $window.addEventListener('touchstart', updateScope);
      }
    };
  }
];

'use strict';

// http://stackoverflow.com/a/872537
function getScrollTop(){
  if ( typeof window.pageYOffset !== 'undefined' ) {
    // most browsers except IE before #9
    return window.pageYOffset;
  } else {
    var b = document.body; // IE 'quirks'
    var d = document.documentElement; // IE with doctype
    return ((d.clientHeight) ? d : b).scrollTop;
  }
}

module.exports = [
  '$rootScope', '$window', '$timeout',
  function BroadcastScrollPositionDirective($rootScope, $window, $timeout) {
    return {
      restrict: 'A',
      link: function($scope, $el, attrs) {
        var el = attrs.assBroadcastScrollPosition ? eval(attrs.assBroadcastScrollPosition) : document.body;
        $rootScope.assBroadcastScrollPosition = 0;
        var p = $timeout();
        function updateScope() {
          $timeout.cancel(p);
          p = $timeout(function(){
            $rootScope.$apply(function(){
              $rootScope.assBroadcastScrollPosition = getScrollTop() - el.offsetHeight + window.innerHeight*2.5;
            });
          });
        }
        $window.addEventListener('scroll', updateScope);
        $window.addEventListener('touchstart', updateScope);
        updateScope();
      }
    };
  }
];

Fix invalid reference before first scroll


document.write("<canvas>")
var Graphics = new Processing(document.querySelector('canvas'));

Graphics.keyPressed = function() {
  World.query("keyboard").forEach(function(e) {
    e.key = Graphics.keyCode;
  });
}

Graphics.keyReleased = function() {
  World.query("keyboard").forEach(function(e) {
    delete e.key;
  });
}

Logic.store.unshift({apply: function() {
  Graphics.background(0)
}});
Logic.addFromFile("/js/backends/graphics/graphics.logic")

Add black background logic to Graphics backend


'use strict';

var express = require('express');

var app = express();
var stationsRoutes = require('./src/routes/stations');

if (!process.env['BIKE_API_KEY']) {
    console.warn('WARNING : The environment variable $BIKE_API_KEY is not configured.');
} else {
    console.log('The $BIKE_API_KEY is ' + process.env['BIKE_API_KEY']);
}

app.use('/api', function (req, res, next) {
    // Allow CORS and set the proper content-type header.
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
    res.header('Content-Type', 'application/json; charset=utf-8');
    next();
});

app.use('/api', stationsRoutes);

app.use('/', express.static('public'));

app.listen(8080, function () {
    console.info('Server running on port 8080.');
});

'use strict';

var express = require('express');

var app = express();
var stationsRoutes = require('./src/routes/stations');

if (!process.env['BIKE_API_KEY']) {
    console.warn('WARNING : The environment variable $BIKE_API_KEY is not configured.');
} else {
    console.log('The $BIKE_API_KEY is ' + process.env['BIKE_API_KEY']);
}

app.use('/api', function (req, res, next) {
    // Allow CORS.
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
    next();
});

app.use('/api', stationsRoutes);

app.use('/', express.static('public'));

app.listen(8080, function () {
    console.info('Server running on port 8080.');
});

Remove useless header setting, since it is already set by express.


import { inject as service } from '@ember/service';
import Component from '@ember/component';
import layout from '../templates/components/cs-editor-switch';

export default Component.extend({
  layout,
  classNames: ['cs-editor-switch'],
  tools: service('cardstack-tools'),
  actions: {
    setEditing(value) {
      this.get('tools').setEditing(value);
    }
  }
});

import { inject as service } from '@ember/service';
import Component from '@ember/component';
import layout from '../templates/components/cs-editor-switch';

export default Component.extend({
  layout,
  classNames: ['cs-editor-switch'],
  tools: service('cardstack-tools'),
  actions: {
    setEditing(value) {
      this.get('tools').setEditing(value);
      if (!value) {
        this.get('tools').openField();
      }
    }
  }
});

Disable opened field when editor is off


import { createElement as h } from 'react'
import PropTypes from 'prop-types'

const Select = (props) => {

	return (
		h('select', {
			className: 'select',
			value: props.value,
			onChange: props.onChange,
			disabled: props.disabled
		},
			props.items.map((item, index) => (
				h('option', {
					key: item.value + index,
					value: item.value
				}, item.label)
			))
		)
	)

}

Select.propTypes = {
	value: PropTypes.string,
	onChange: PropTypes.func.isRequired,
	items: PropTypes.arrayOf(
		PropTypes.shape({
			value: PropTypes.string.isRequired,
			label: PropTypes.string.isRequired
		})
	).isRequired
}

export default Select

import { createElement as h } from 'react'
import PropTypes from 'prop-types'

const Select = (props) => {

	return (
		h('select', {
			className: 'select',
			id: props.id,
			required: props.required,
			disabled: props.disabled,
			value: props.value,
			onChange: props.onChange
		},
			props.items.map((item, index) => (
				h('option', {
					key: item.value + index,
					value: item.value
				}, item.label)
			))
		)
	)

}

Select.propTypes = {
	id: PropTypes.string,
	required: PropTypes.bool,
	disabled: PropTypes.bool,
	value: PropTypes.string,
	onChange: PropTypes.func.isRequired,
	items: PropTypes.arrayOf(
		PropTypes.shape({
			value: PropTypes.string.isRequired,
			label: PropTypes.string.isRequired
		})
	).isRequired
}

export default Select

Add more props to select field


'use strict';

var Hapi = require('hapi');

var server = new Hapi.Server();

if( process.env.PORT ) {
  server.connection({ port: process.env.PORT });
}
else {
  server.connection({ port: 1337 });
}

server.route({
  method: 'GET',
  path: '/',
  handler: function (request, reply) {
    reply('Hello, world!');
  }
});

server.route({
  method: 'GET',
  path: '/{name}',
  handler: function (request, reply) {
    reply('Hello, ' + encodeURIComponent(request.params.name) + '!');
  }
});

server.start(function () {
  console.log('Server running at:', server.info.uri);
});

'use strict';

var Hapi = require('hapi');

var server = new Hapi.Server();

if( process.env.PORT ) {
  server.connection({ port: process.env.PORT });
}
else {
  server.connection({ port: 1337 });
}

server.route({
  method: 'GET',
  path: '/',
  handler: function (request, reply) {
    reply('Hello, world!');
  }
});

server.route({
  method: 'GET',
  path: '/{name}',
  handler: function (request, reply) {
    reply('Hello, ' + encodeURIComponent(request.params.name) + '!');
  }
});

server.route({
  method : "GET",
  path : '/assets/{param*}',
  handler : {
    directory : {
      path : 'bower_components',
  listing : true
    }
  }
});

server.start(function () {
  console.log('Server running at:', server.info.uri);
});

Add hapi route to bower packages.


Package.describe({
  summary: 'CSS minifier',
  version: '1.5.3'
});

Npm.depends({
  postcss: '7.0.32',
  cssnano: '4.1.10'
});

Package.onUse(function (api) {
  api.use('ecmascript');
  api.mainModule('minifier.js', 'server');
  api.export('CssTools');
});

Package.onTest(function (api) {
  api.use('ecmascript');
  api.use('tinytest');
  api.addFiles([
    'minifier-tests.js',
    'urlrewriting-tests.js'
  ], 'server');
});

Package.describe({
  summary: 'CSS minifier',
  version: '1.5.4'
});

Npm.depends({
  postcss: '8.2.10',
  cssnano: '4.1.10'
});

Package.onUse(function (api) {
  api.use('ecmascript');
  api.mainModule('minifier.js', 'server');
  api.export('CssTools');
});

Package.onTest(function (api) {
  api.use('ecmascript');
  api.use('tinytest');
  api.addFiles([
    'minifier-tests.js',
    'urlrewriting-tests.js'
  ], 'server');
});

Update postcss from 7.0.32 to 8.2.10


/* eslint-disable new-cap */
/**
 * This source code is licensed under the MIT-style license found in the
 * LICENSE file in the root directory of this source tree. *
 *
 * @providesModule setupTestFrameworkScriptFile
 * @flow
 */

import enzymeMatchers from 'enzyme-matchers';
import serializer from 'enzyme-to-json/serializer';

declare var expect: Function;
declare var beforeEach: Function;

// add the snapshot serializer for Enzyme wrappers
expect.addSnapshotSerializer(serializer);

// add methods!
beforeEach(() => {
  const matchers = {};

  Object.keys(enzymeMatchers).forEach(matcherKey => {
    const matcher = {
      [matcherKey](wrapper, ...args) {
        const result = enzymeMatchers[matcherKey].call(this, wrapper, ...args);

        let message = this.isNot ? result.negatedMessage : result.message;

        if (result.contextualInformation.expected) {
          message += `\n${this.utils.RECEIVED_COLOR(
            result.contextualInformation.expected
          )}`;
        }

        if (result.contextualInformation.actual) {
          message += `\n${this.utils.EXPECTED_COLOR(
            result.contextualInformation.actual
          )}`;
        }

        result.message = () => message;

        return result;
      },
    }[matcherKey];

    matchers[matcherKey] = matcher;
  });

  expect.extend(matchers);
});

/* eslint-disable new-cap */
/**
 * This source code is licensed under the MIT-style license found in the
 * LICENSE file in the root directory of this source tree. *
 *
 * @providesModule setupTestFrameworkScriptFile
 * @flow
 */

import enzymeMatchers from 'enzyme-matchers';
import serializer from 'enzyme-to-json/serializer';

declare var expect: Function;
declare var beforeEach: Function;

// add the snapshot serializer for Enzyme wrappers
expect.addSnapshotSerializer(serializer);

// add methods!
beforeEach(() => {
  const matchers = {};

  Object.keys(enzymeMatchers).forEach(matcherKey => {
    const matcher = {
      [matcherKey](wrapper, ...args) {
        const result = enzymeMatchers[matcherKey].call(this, wrapper, ...args);

        let message = this.isNot ? result.negatedMessage : result.message;

        if (result.contextualInformation.expected) {
          message += `\n${this.utils.RECEIVED_COLOR(
            result.contextualInformation.expected
          )}`;
        }

        if (result.contextualInformation.actual) {
          message += `\n${this.utils.EXPECTED_COLOR(
            result.contextualInformation.actual
          )}`;
        }

        return {
          ...result,
          message: () => message,
        };
      },
    }[matcherKey];

    matchers[matcherKey] = matcher;
  });

  expect.extend(matchers);
});

Fix flow for message function


"use strict";

(function (app) {
    app.AppComponent = ng.core
        .Component({
            selector: "my-app",
            template: "
My First Angular 2 (2.0.0-beta.0) App
"
        })
        .Class({
            constructor: function () {}
        });
}(window.app || (window.app = {})));

"use strict";

(function (app) {
    app.AppComponent = ng.core
        .Component({
            selector: "my-app",
            template: "
My First Angular 2 App
"
        })
        .Class({
            constructor: function () {}
        });
}(window.app || (window.app = {})));

Change text in basic template.


"use strict";

function sendToggle(tabs) {
  let id = tabs[0].id;
  browser.tabs.sendMessage(id, {request: 'toggle'}).then(m => {
    if (m.toggle) {
      browser.browserAction.setBadgeText({text: "", tabId: id});
    } else {
      browser.browserAction.setBadgeText({text: "🞬", tabId: id});
    }
  });
}

browser.browserAction.onClicked.addListener(() => {
  browser.tabs.query({currentWindow: true, active: true}).then(sendToggle);
});

/* Copyright (c) 2016 Dmitri Kourennyi */
/* See the file COPYING for copying permission. */
'use strict';

Remove unused code in background script


import React, { Component } from 'react';

class CommentStream extends Component {
  render() {
    return (

    );
  }
}

export default CommentStream;

import React, { Component } from 'react';

class CommentStream extends Component {
  render() {
    return (

        {this.props.events.map((event, index) => (

{JSON.stringify(event)}

        ))}

    );
  }
}

CommentStream.propTypes = {
  events: React.PropTypes.arrayOf(React.PropTypes.object).isRequired
}

export default CommentStream;

Make a kinda ghetto comment stream dump


/*jshint node:true*/
module.exports = {
  "framework": "qunit",
  "test_page": "tests/index.html?hidepassed",
  "disable_watching": true,
  "launch_in_ci": [
    "PhantomJS"
  ],
  "launch_in_dev": [
    "PhantomJS",
    "Chrome"
  ]
};

/*jshint node:true*/
module.exports = {
  "framework": "qunit",
  "test_page": "tests/index.html?hidepassed",
  "disable_watching": true,
  "launch_in_ci": [
    "PhantomJS"
  ],
  "launch_in_dev": [
    "PhantomJS",
    "Chrome"
  ],
  "reporter": "dot"
};

Use the dot test reporter.


function focusDoc(browser, docType) {
  const devServer = browser.globals.devServerURL;

  browser.url(`${devServer}/`);
  browser.expect.element('#app').to.be.visible.before(5000);

  const createButton = `#button-create-${docType}`;
  const docToFocus = `.${docType}`;

  browser
    .click(createButton)
    .pause(500);

  browser
    .click(docToFocus)
    .pause(500);

  browser
    .expect.element('#button-delete .md-inactive')
    .to.not.be.present;

  browser
    .expect.element('#button-download .md-inactive')
    .to.not.be.present;
}
describe('FileManager\'s download and delete button', function() {
  after((browser, done) => {
    browser.end(() => done());
  });

  it('should be enable when a file is focused', (browser) => {
    focusDoc(browser, 'file');
  });

  it('should be created when a folder is focused', (browser) => {
    focusDoc(browser, 'folder');
  });
});

function focusDoc(browser, docType) {
  const devServer = browser.globals.devServerURL;

  browser.url(`${devServer}/`);
  browser.expect.element('#app').to.be.visible.before(5000);

  const createButton = `#button-create-${docType}`;
  const docToFocus = `.${docType}`;

  browser
    .click(createButton)
    .pause(500);

  browser
    .click(docToFocus)
    .pause(500);

  browser
    .expect.element('#button-delete .md-inactive')
    .to.not.be.present;

  browser
    .expect.element('#button-download .md-inactive')
    .to.not.be.present;
}
describe('FileManager\'s download and delete button', function() {
  after((browser, done) => {
    browser.end(() => done());
  });

  it('should be enabled when a file is focused', (browser) => {
    focusDoc(browser, 'file');
  });

  it('should be enabled when a folder is focused', (browser) => {
    focusDoc(browser, 'folder');
  });
});

Fix wordings of test statements


const Twit = require('twit');

const secrets = require('./secrets');

var T = new Twit({
  consumer_key: secrets.consumer_key,
  consumer_secret: secrets.consumer_secret,
  access_token: secrets.access_token,
  access_token_secret: secrets.access_token_secret,
});

var params = { q: 'banana', count: 3 };

function callback(err, data, response) {
  var tweets = data.statuses;
  for (var i = 0; i < tweets.length; i++) {
    console.log(tweets[i].text);
  }
}

T.get('search/tweets', params, callback);

Test get request to Twitter


#!/usr/bin/env node
import pcap from 'pcap';
import yargs from 'yargs';

import ArpProbes from './ArpProbes';
import MacAddresses from './MacAddresses';
import NetworkInterfaces from './NetworkInterfaces';

if (require.main === module) {
  let parser = yargs
    .usage('Usage: $0 <command> [options]')
    .command('scan', 'Scan for ARP probes')
    .example(
      '$0 scan -i wlan0',
      'Scan for ARP probes on the given network interface'
    )
    .help('h')
    .alias('h', 'help')
    .version(() => require('../package.json').version)
    .alias('i', 'interface')
    .nargs('i', 1)
    .default('i', NetworkInterfaces.getDefault())
    .describe('i', 'The network interface on which to listen');
  let { argv } = parser;
  let commands = new Set(argv._);
  if (!commands.size) {
    console.log(parser.help());
  } else if (commands.has('scan')) {
    let pcapSession = ArpProbes.createCaptureSession(argv.interface);
    pcapSession.addListener('packet', rawPacket => {
      let packet = pcap.decode(rawPacket);
      let sourceMacAddress = MacAddresses.getEthernetSource(packet);
      console.log('Detected an ARP probe from %s', sourceMacAddress);
    });
    console.log('Scanning for ARP probes...');
  }
}

#!/usr/bin/env node
import pcap from 'pcap';
import yargs from 'yargs';

import ArpProbes from './ArpProbes';
import MacAddresses from './MacAddresses';
import NetworkInterfaces from './NetworkInterfaces';

if (require.main === module) {
  let parser = yargs
    .usage('Usage: $0 <command> [options]')
    .command('scan', 'Scan for ARP probes')
    .example(
      '$0 scan -i wlan0',
      'Scan for ARP probes on the given network interface'
    )
    .help('h')
    .alias('h', 'help')
    .version(() => require('../package.json').version)
    .alias('i', 'interface')
    .nargs('i', 1)
    .default('i', NetworkInterfaces.getDefault())
    .describe('i', 'The network interface on which to listen');
  let { argv } = parser;
  let commands = new Set(argv._);
  if (!commands.size) {
    console.log(parser.help());
  } else if (commands.has('scan')) {
    let interfaceName = argv.interface;
    let pcapSession = ArpProbes.createCaptureSession(interfaceName);
    pcapSession.addListener('packet', rawPacket => {
      let packet = pcap.decode(rawPacket);
      let sourceMacAddress = MacAddresses.getEthernetSource(packet);
      console.log('Detected an ARP probe from %s', sourceMacAddress);
    });
    console.log('Scanning for ARP probes on %s...', interfaceName);
  }
}

Print out the interface name


var Fluxxor = require('fluxxor');
var _ = require('lodash-node');

class Store {
  constructor(name, actions) {
    var self = this;
    this.name = name;
    this.loading = false;
    this.data = {};
    this.emit = this.noop;

    this.storeActions = {};
    this.storeActions[`LOAD_${name}`] = this.onLoading;

    this.flux = Fluxxor.createStore({
      initialize() {
        self.emit = this.emit;
        this.bindActions(_.merge(self.storeActions, actions));
      }
    });
  }

  onLoading() {
    this.loading = true;
    this.emit('change');
  }

  getFlux() {
    return this.flux;
  }

  noop() {}
}

module.exports = Store;

var Fluxxor = require('fluxxor');

class Store {
  constructor(name, actions) {
    var self = this;
    this.name = name;
    this.emit = this.noop;

    this.flux = Fluxxor.createStore({
      initialize() {
        self.emit = this.emit;
        this.bindActions(actions);
      }
    });
  }

  onLoading() {
    this.loading = true;
    this.emit('change');
  }

  getFlux() {
    return this.flux;
  }

  noop() {}
}

module.exports = Store;

Remove dup code in store


window.onload = function() {
    document.getElementById('player_display_track_metadata').onchange = generateEmbedSrc;
}

function generateEmbedSrc()
{

}

function generateEmbedSrc()
{
    var $embedCodeParams = "?";
    var $streamMode = getStreamMode();
    if ($streamMode == "b") {
        var $stream = $("input[name=player_stream_url]:radio:checked").val();
        $embedCodeParams += "stream-mode=b&stream="+$stream;
    } else if ($streamMode == "a") {
        $embedCodeParams += "stream-mode=a";
    }
    $embedCodeParams += "\"";

    $("input[name=player_embed_src]").val(function(index, value) {
        return value.replace(/\?.*?"/, $embedCodeParams);
    });
}

function getStreamMode() {
    return $("input[name=player_stream_mode]:radio:checked").val();
}

$(document).ready(function() {
    $("#player_stream_mode-element").change(function() {
        var $streamMode = getStreamMode();
        if ($streamMode == "a") {
            $("#player_stream_url-element input[type='radio']").attr("disabled", "disabled");
        } else if ($streamMode == "b") {
            $("#player_stream_url-element input[type='radio']").removeAttr("disabled");
        }

        generateEmbedSrc();
    });

    $("#player_stream_url-element").change(function() {
        generateEmbedSrc();
    });
});

Embed Player -> Update embed src code and preview when an option changes


'use strict';

describe('geneanetCustomCamera', function() {
    beforeEach(module('geneanetCustomCamera'));

    beforeEach(module(function(geneanetCustomCameraProvider) {
        return function() {
            geneanetCustomCameraProvider.setOptionMiniature(false);
        };
    }));

    it('should have the miniature option disabled.', function() {
        inject(function(geneanetCustomCamera) {
            expect(geneanetCustomCamera.getOptionMiniature()).not.toBeTruthy();
        });
    });
});

'use strict';

describe('geneanetCustomCamera', function() {
    beforeEach(module('geneanetCustomCamera'));

    it('should have options values as values set by the provider', function() {
        var optionMiniature = false;
        var optionSaveInGallery = true;
        var optionCameraBackgroundColor = '#012345';
        var optionCameraBackgroundColorPressed = '#678901';
        var optionQuality = '12';
        var optionOpacity = false;
        var optionSwitchFlash = true;
        var optionSwitchCamera = false;

        // init service
        module(function(geneanetCustomCameraProvider) {
            return function() {
                geneanetCustomCameraProvider.setOptionMiniature(optionMiniature);
                geneanetCustomCameraProvider.setOptionSaveInGallery(optionSaveInGallery);
                geneanetCustomCameraProvider.setOptionCameraBackgroundColor(optionCameraBackgroundColor);
                geneanetCustomCameraProvider.setOptionCameraBackgroundColorPressed(optionCameraBackgroundColorPressed);
                geneanetCustomCameraProvider.setOptionQuality(optionQuality);
                geneanetCustomCameraProvider.setOptionOpacity(optionOpacity);
                geneanetCustomCameraProvider.setOptionSwitchFlash(optionSwitchFlash);
                geneanetCustomCameraProvider.setOptionSwitchCamera(optionSwitchCamera);
            };
        });

        inject(function(geneanetCustomCamera) {
            expect(geneanetCustomCamera.getOptionMiniature()).toEqual(optionMiniature);
            expect(geneanetCustomCamera.getOptionSaveInGallery()).toEqual(optionSaveInGallery);
            expect(geneanetCustomCamera.getOptionCameraBackgroundColor()).toEqual(optionCameraBackgroundColor);
            expect(geneanetCustomCamera.getOptionCameraBackgroundColorPressed()).toEqual(optionCameraBackgroundColorPressed);
            expect(geneanetCustomCamera.getOptionQuality()).toEqual(optionQuality);
            expect(geneanetCustomCamera.getOptionOpacity()).toEqual(optionOpacity);
            expect(geneanetCustomCamera.getOptionSwitchFlash()).toEqual(optionSwitchFlash);
            expect(geneanetCustomCamera.getOptionSwitchCamera()).toEqual(optionSwitchCamera);
        });

        // @TODO: test set default flash
    });
});

Complete the test to configure the service.


/* eslint-disable class-methods-use-this */
/*
 * Copyright 2019 Expedia Group
 *
 *         Licensed under the Apache License, Version 2.0 (the "License");
 *         you may not use this file except in compliance with the License.
 *         You may obtain a copy of the License at
 *
 *             http://www.apache.org/licenses/LICENSE-2.0
 *
 *         Unless required by applicable law or agreed to in writing, software
 *         distributed under the License is distributed on an "AS IS" BASIS,
 *         WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *         See the License for the specific language governing permissions and
 *         limitations under the License.
 */

import store from '../../../serviceInsights/stores/serviceInsightsStore';

export class ServiceInsightsTabStateStore {
    search = null;
    isAvailable = false;
    hasValidSearch = false;

    init(search) {
        this.search = search;

        // is Service Insights enabled in the appliation config?
        const enableServiceInsights = (window.haystackUiConfig && window.haystackUiConfig.enableServiceInsights) || false;

        // If user is directly accessing URL, show this feature
        const isAccessingServiceInsights = this.search.tabId === 'serviceInsights';

        // has required minimal search terms
        this.hasValidSearch = !!(search.serviceName || search.traceId);

        this.isAvailable = enableServiceInsights && (this.hasValidSearch || isAccessingServiceInsights);
    }

    fetch() {
        return store;
    }
}

export default new ServiceInsightsTabStateStore();

/* eslint-disable class-methods-use-this */
/*
 * Copyright 2019 Expedia Group
 *
 *         Licensed under the Apache License, Version 2.0 (the "License");
 *         you may not use this file except in compliance with the License.
 *         You may obtain a copy of the License at
 *
 *             http://www.apache.org/licenses/LICENSE-2.0
 *
 *         Unless required by applicable law or agreed to in writing, software
 *         distributed under the License is distributed on an "AS IS" BASIS,
 *         WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *         See the License for the specific language governing permissions and
 *         limitations under the License.
 */

import store from '../../../serviceInsights/stores/serviceInsightsStore';

export class ServiceInsightsTabStateStore {
    search = null;
    isAvailable = false;
    hasValidSearch = false;

    init(search) {
        this.search = search;

        // is Service Insights enabled in the appliation config?
        const enableServiceInsights = (window.haystackUiConfig && window.haystackUiConfig.enableServiceInsights) || false;

        // If user is directly accessing URL, show this feature
        const isAccessingServiceInsights = this.search.tabId === 'serviceInsights';

        // has required minimal search terms
        this.hasValidSearch = !!(search.serviceName || search.traceId);

        this.isAvailable = enableServiceInsights && (this.hasValidSearch || isAccessingServiceInsights);
    }

    fetch() {
        // Copy `hasValidSearch` so serviceInsight reactJS component can leverage
        store.hasValidSearch = this.hasValidSearch;
        return store;
    }
}

export default new ServiceInsightsTabStateStore();

Fix bug in service insights


/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

var AddHasAttachmentHeaderCompose = {
  HEADER: 'X-Mozilla-Has-Attachment',

  addHeader: function(aCompFields) {
    // You don't need to remove old value (for mails generated by "edit as new",
    // or edited from a draft) because custom header is automatically overridden
    // with the latest value.
    aCompFields.otherRandomHeaders += this.HEADER + ': '+ this.headerValue + '\r\n';
  },

  get headerValue() {
    var attachmentsBacket = GetMsgAttachmentElement();
    var attachmentsCount = attachmentsBacket.itemCount;
    return attachmentsCount > 0 ? 'yes' : 'no';
  }
};

(function() {
  var originalRecipients2CompFields = window.Recipients2CompFields;
  window.Recipients2CompFields = function Recipients2CompFields(aCompFields) {
    var returnValue = originalRecipients2CompFields.apply(this, arguments);
    AddHasAttachmentHeaderCompose.addHeader(aCompFields);
    return returnValue;
  };
})();

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

var AddHasAttachmentHeaderCompose = {
  HEADER: 'X-Mozilla-Has-Attachment',

  addHeader: function(aCompFields) {
    // You don't need to remove old value (for mails generated by "edit as new",
    // or edited from a draft) because custom header is automatically overridden
    // with the latest value.
    aCompFields.setHeader(this.HEADER, this.headerValue);
  },

  get headerValue() {
    var attachmentsBacket = GetMsgAttachmentElement();
    var attachmentsCount = attachmentsBacket.itemCount;
    return attachmentsCount > 0 ? 'yes' : 'no';
  }
};

(function() {
  var originalRecipients2CompFields = window.Recipients2CompFields;
  window.Recipients2CompFields = function Recipients2CompFields(aCompFields) {
    var returnValue = originalRecipients2CompFields.apply(this, arguments);
    AddHasAttachmentHeaderCompose.addHeader(aCompFields);
    return returnValue;
  };
})();

Support Thunderbird 52 and later


'use strict';

module.exports = function(environment) {
  let ENV = {
    modulePrefix: 'dummy',
    environment,
    rootURL: '/',
    locationType: 'auto',
    EmberENV: {
      EXTEND_PROTOTYPES: true,
      FEATURES: {
        // Here you can enable experimental features on an ember canary build
        // e.g. 'with-controller': true
      }
    },

    APP: {
      // Here you can pass flags/options to your application instance
      // when it is created
    }
  };

  if (environment === 'development') {
    // ENV.APP.LOG_RESOLVER = true;
    // ENV.APP.LOG_ACTIVE_GENERATION = true;
    // ENV.APP.LOG_TRANSITIONS = true;
    // ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
    // ENV.APP.LOG_VIEW_LOOKUPS = true;
  }

  if (environment === 'test') {
    // Testem prefers this...
    ENV.locationType = 'none';

    // keep test console output quieter
    ENV.APP.LOG_ACTIVE_GENERATION = false;
    ENV.APP.LOG_VIEW_LOOKUPS = false;

    ENV.APP.rootElement = '#ember-testing';
    ENV.APP.autoboot = false;
  }

  if (environment === 'production') {
    // Allow ember-cli-addon-docs to update the rootURL in compiled assets
    ENV.rootURL = 'ADDON_DOCS_ROOT_URL';
    ENV.locationType = 'hash';
  }

  return ENV;
};

'use strict';

module.exports = function(environment) {
  let ENV = {
    modulePrefix: 'dummy',
    environment,
    rootURL: '/',
    locationType: 'auto',
    EmberENV: {
      EXTEND_PROTOTYPES: true,
      FEATURES: {
        // Here you can enable experimental features on an ember canary build
        // e.g. 'with-controller': true
      }
    },

    APP: {
      // Here you can pass flags/options to your application instance
      // when it is created
    }
  };

  if (environment === 'development') {
    // ENV.APP.LOG_RESOLVER = true;
    // ENV.APP.LOG_ACTIVE_GENERATION = true;
    // ENV.APP.LOG_TRANSITIONS = true;
    // ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
    // ENV.APP.LOG_VIEW_LOOKUPS = true;
  }

  if (environment === 'test') {
    // Testem prefers this...
    ENV.locationType = 'none';

    // keep test console output quieter
    ENV.APP.LOG_ACTIVE_GENERATION = false;
    ENV.APP.LOG_VIEW_LOOKUPS = false;

    ENV.APP.rootElement = '#ember-testing';
    ENV.APP.autoboot = false;
  }

  if (environment === 'production') {
    ENV.locationType = 'hash';
  }

  return ENV;
};

Remove rootURL so netlify can deploy it