const webpack = require('webpack');
const webpackMerge = require('webpack-merge');
const commonConfig = require('./webpack.common.js');
const ENV = process.env.NODE_ENV = process.env.ENV = 'production';

module.exports = webpackMerge(commonConfig, {
    devtool: 'source-map',

    externals: {
        'react': 'React',
        'react-dom': 'ReactDOM'
    },

    performance: {
        hints: "warning"
    },

    plugins: [
        new webpack.optimize.UglifyJsPlugin({
            sourceMap: true,
            compress: true,
            mangle: {
                screw_ie8: true,
                keep_fnames: true
            },
            compress: {
                warnings: false,
                screw_ie8: true
            },
            comments: false
        })
    ]
});

const webpack = require('webpack');
const webpackMerge = require('webpack-merge');
const commonConfig = require('./webpack.common.js');
const ENV = process.env.NODE_ENV = process.env.ENV = 'production';

module.exports = webpackMerge(commonConfig, {
    devtool: 'source-map',

    externals: {
        'react': 'React',
        'react-dom': 'ReactDOM'
    },

    performance: {
        hints: "warning"
    },

    plugins: [
        new webpack.optimize.UglifyJsPlugin({
            sourceMap: true,
            mangle: {
                screw_ie8: true,
                keep_fnames: true
            },
            compress: {
                warnings: false,
                screw_ie8: true
            },
            comments: false
        })
    ]
});

Fix duplicate key in webpack config


/*
 * Object that contains Game initialization data.
 */

export default class {
  constructor(canvasWidth, canvasHeight) {
    this.gameInits = {};

    this._generateInitialSettings(canvasWidth, canvasHeight);
  }

  _generateInitialSettings(canvasWidth, canvasHeight) {
    this.gameInits.paddle = (()=> {
      let width = 60;
      let height = 6;
      return {
        x: (canvasWidth - width) / 2,
        y: canvasHeight - height,
        color: '#555555',
        width: width,
        height: height
      };
    })();
    this.gameInits.ball = (()=> {
      return {
        x: canvasWidth / 2,
        y: canvasHeight - 30,
        velocityX: 1,
        velocityY: 1,
        color: '#555555',
        radius: 10,
      };
    })();
  }
};

/*
 * Object that contains Game initialization data.
 */

export default class {
  constructor(canvasWidth, canvasHeight) {
    this.gameInits = {};

    this._generateInitialSettings(canvasWidth, canvasHeight);
  }

  _generateInitialSettings(canvasWidth, canvasHeight) {
    this.gameInits.paddle = (()=> {
      let width = 60;
      let height = 6;
      return {
        x: (canvasWidth - width) / 2,
        y: canvasHeight - height,
        color: '#555555',
        width: width,
        height: height
      };
    })();
    this.gameInits.ball = (()=> {
      return {
        x: canvasWidth / 2,
        y: canvasHeight - 30,
        velocityX: 1,
        velocityY: -1,
        color: '#555555',
        radius: 10,
      };
    })();
  }
};

Make ball start by flying upwards


$(document).ready(function(){

	$("#backbtn-settings").click({
        param: 'route_view'
    }, showView);

	// first button in settings is to reset favoritelist
	// an empty list gets assigned to the favoritelist in localforage
	$("#clearbtn").click(function(){
		localforage.setItem("favList",[],function(err){});
		$("#route_view").load("../route.html");
	});
});

$(document).ready(function(){

	$("#backbtn-settings").click({
        param: 'route_view'
    }, showView);

	// first button in settings is to reset favoritelist
	// an empty list gets assigned to the favoritelist in localforage
	$("#clearbtn").click(function(){
		localforage.setItem("favList",[],function(err){});
		location.reload();
	});
});

Fix reload after FavList clear to show changes immediately.


module.exports = {
	// browser: 'google chrome',
	reloadDelay: 250,
	open: false,
	files: ['build/*.css', 'build/*.js', 'build/*.html'],
	server: {
		baseDir: './build',
	},
	notify: false,
}

module.exports = {
	// browser: 'google chrome',
	open: false,
	files: ['build/*.css', 'build/*.js', 'build/*.html'],
	server: {
		baseDir: './build',
	},
	notify: false,
}

Remove the browser-sync reload delay


exports.tests = [
	{
		css: '.foo body > h2 {}',
		metrics: {
			redundantBodySelectors: 1
		}
	},
	{
		css: 'body ul li a {}',
		metrics: {
			redundantBodySelectors: 1
		}
	},
	{
		css: 'body#foo ul li a {}',
		metrics: {
			redundantBodySelectors: 1
		}
	},
	{
		css: 'body > h1 {}',
		metrics: {
			redundantBodySelectors: 0
		}
	},
	{
		css: 'html > body #foo .bar {}',
		metrics: {
			redundantBodySelectors: 0
		}
	},
	{
		css: 'body {}',
		metrics: {
			redundantBodySelectors: 0
		}
	},
	{
		css: 'body.mainpage {}',
		metrics: {
			redundantBodySelectors: 0
		}
	},
	{
		css: 'body.foo ul li a {}',
		metrics: {
			redundantBodySelectors: 0
		}
	}
];

exports.tests = [
	{
		css: '.foo body > h2 {}',
		metrics: {
			redundantBodySelectors: 1
		}
	},
	{
		css: 'body ul li a {}',
		metrics: {
			redundantBodySelectors: 1
		}
	},
	{
		css: 'body#foo ul li a {}',
		metrics: {
			redundantBodySelectors: 1
		}
	},
	{
		css: 'body > h1 {}',
		metrics: {
			redundantBodySelectors: 0
		}
	},
	{
		css: 'html > body #foo .bar {}',
		metrics: {
			redundantBodySelectors: 0
		}
	},
	{
		css: 'body {}',
		metrics: {
			redundantBodySelectors: 0
		}
	},
	{
		css: 'body.mainpage {}',
		metrics: {
			redundantBodySelectors: 0
		}
	},
	{
		css: 'body.foo ul li a {}',
		metrics: {
			redundantBodySelectors: 0
		}
	},
	{
		css: 'html.modal-popup-mode body {}',
		metrics: {
			redundantBodySelectors: 0
		}
	}
];

Add a unit test case


var Clean             = require('clean-webpack-plugin'),
    ExtractTextPlugin = require('extract-text-webpack-plugin'),
    webpack           = require('webpack'),
    webpackConfig     = require('webpack-config');

var config = webpackConfig.fromCwd().merge({
    output: {
        filename: 'videojs.chapter-thumbnails.min.js'
    }
});

config.plugins = [
    new Clean([
        'build'
    ]),

    new ExtractTextPlugin('videojs.chapter-thumbnails.min.css'),

    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin()
];

module.exports = config;

var Clean             = require('clean-webpack-plugin'),
    ExtractTextPlugin = require('extract-text-webpack-plugin'),
    webpack           = require('webpack'),
    webpackConfig     = require('webpack-config');

var config = webpackConfig.fromCwd().merge({
    output: {
        filename: 'videojs.chapter-thumbnails.min.js'
    }
});

config.plugins = [
    new Clean([
        'build'
    ]),

    new ExtractTextPlugin('videojs.chapter-thumbnails.min.css'),

    new webpack.optimize.DedupePlugin(),
    new webpack.optimize.UglifyJsPlugin({
        comments: false
    })
];

module.exports = config;

Remove comments from minified version.


"use strict";
if (typeof localStorage !== "undefined"){
	for(var key in localStorage){
		if (localStorage.hasOwnProperty(key) && key != "debug") exports[key] = localStorage[key];
	}
}
exports.register = function(opt, ele, nopersist){
	var field = ele.type == "checkbox" ? "checked" : "value";
	if (exports[opt]) ele[field] = exports[opt];
	if (!nopersist && typeof localStorage !== "undefined"){
		ele.addEventListener("input", function() {
			if (this[field]){
				exports[opt] = localStorage[opt] = this[field];
			}else{
				delete localStorage[opt];
				delete exports[opt];
			}
		});
	}else{
		ele.addEventListener("input", function() {
			exports[opt] = field == "checked" && !this.checked ? "" : this[field];
		});
	}
}

"use strict";
if (typeof localStorage !== "undefined"){
	for(var key in localStorage){
		if (localStorage.hasOwnProperty(key) && key != "debug") exports[key] = localStorage[key];
	}
}
exports.register = function(opt, ele, nopersist){
	var field = ele.type == "checkbox" ? "checked" : "value";
	if (exports[opt]) ele[field] = exports[opt];
	if (!nopersist && typeof localStorage !== "undefined"){
		ele.addEventListener("change", function() {
			if (this[field]){
				exports[opt] = localStorage[opt] = this[field];
			}else{
				delete localStorage[opt];
				delete exports[opt];
			}
		});
	}else{
		ele.addEventListener("change", function() {
			exports[opt] = field == "checked" && !this.checked ? "" : this[field];
		});
	}
}

Revert using input event, change seems good enough


import { camelToDash } from '@hybrids/core/src/utils';
import { error } from '../debug';

export default function style({ node, expr }, ...propertyNames) {
  if (!propertyNames.length) {
    return (list, { type: globalType, oldValue, changelog }) => {
      switch (globalType) {
        case 'modify':
          Object.keys(changelog).forEach((key) => {
            switch (changelog[key].type) {
              case 'delete':
                node.style.removeProperty(camelToDash(key));
                break;
              default:
                node.style.setProperty(camelToDash(key), list[key]);
            }
          });
          break;
        default:
          if (list) {
            if (typeof list !== 'object') {
              error(TypeError, "style: '%evaluate' must be an object: %type", { evaluate: expr.evaluate, type: typeof list });
            }
            Object.keys(list).forEach(key => node.style.setProperty(camelToDash(key), list[key]));
          } else if (typeof oldValue === 'object' && oldValue !== null) {
            Object.keys(oldValue).forEach(key => node.style.removeProperty(camelToDash(key)));
          }
      }
    };
  }

  return (value) => {
    propertyNames.map(camelToDash).forEach(key => node.style.setProperty(key, value));
  };
}

import { error } from '../debug';

function camelToDash(str) {
  return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
}

export default function style({ node, expr }, ...propertyNames) {
  if (!propertyNames.length) {
    return (list, { type: globalType, oldValue, changelog }) => {
      switch (globalType) {
        case 'modify':
          Object.keys(changelog).forEach((key) => {
            switch (changelog[key].type) {
              case 'delete':
                node.style.removeProperty(camelToDash(key));
                break;
              default:
                node.style.setProperty(camelToDash(key), list[key]);
            }
          });
          break;
        default:
          if (list) {
            if (typeof list !== 'object') {
              error(TypeError, "style: '%evaluate' must be an object: %type", { evaluate: expr.evaluate, type: typeof list });
            }
            Object.keys(list).forEach(key => node.style.setProperty(camelToDash(key), list[key]));
          } else if (typeof oldValue === 'object' && oldValue !== null) {
            Object.keys(oldValue).forEach(key => node.style.removeProperty(camelToDash(key)));
          }
      }
    };
  }

  return (value) => {
    propertyNames.map(camelToDash).forEach(key => node.style.setProperty(key, value));
  };
}

Fix remove core source dependency


'use strict';

var jf = require('../../'),
    expect    = require('chai').expect,
    http = require('http');

var count = 0;
function testValue(){
  count ++;
  return { num: count }
}

let server = http.createServer(
  (request, response) => {
    response.writeHead(200, {'Content-Type': 'application/json'});
    response.end( JSON.stringify( testValue() ) );
}).listen(8080);

describe('Download function ', function () {
  this.timeout(10000);
  it('should download JSON from web server for each exec()', function (done) {

    let downloadedJson =
      jf.download(
        'http://localhost:8080',
        function * (){ yield './' + Math.random() + '.json'; } );

    downloadedJson
    .io( ( json ) => { expect( json.num ).to.equal( 1 ) }).exec();

    setTimeout(
      function(){
      },
      100);

    downloadedJson
    .io( ( json ) => { expect( json.num ).to.equal( 2 ) })
    .pass( () => {
      done();
      server.close();
    } )
    .exec();

  });

});

'use strict';

var jf = require('../../'),
    expect    = require('chai').expect,
    http = require('http');

var count = 0;
function testValue(){
  count ++;
  return { num: count }
}

let server = http.createServer(
  (request, response) => {
    response.writeHead(200, {'Content-Type': 'application/json'});
    response.end( JSON.stringify( testValue() ) );
}).listen(8080);

describe('Download function ', function () {
  this.timeout(10000);
  it('should download JSON from web server for each exec()', function (done) {

    let downloadedJson =
      jf.download(
        'http://localhost:8080',
        function * (){ yield './' + Math.random() + '.json'; } );

    downloadedJson
    .io( ( json ) => { expect( json.num ).to.equal( 1 ) })
    .pass( () => {
      downloadedJson
      .io( ( json ) => { expect( json.num ).to.equal( 2 ) })
      .pass( () => {
        done();
        server.close();
      } )
      .exec();
    })
    .exec();

    setTimeout(
      function(){
      },
      100);

  });

});

Fix bug of test code


import { Meteor } from 'meteor/meteor'

Meteor.startup(function () {
    $.material.init();
});

Meteor.call("gitVersionInfoUpdate");

import { Meteor } from 'meteor/meteor'

Meteor.call("gitVersionInfoUpdate");

Remove startup code because $.material is undefined


ManageIQ.angular.app.component('verifyButton', {
  bindings: {
    validate: '<',
    enabled: '<',
    validateUrl: '@',
    restful: '<',
    valtype: '<',
    buttonLabels: '<',
  },
  controllerAs: 'vm',
  controller: ['$scope', function($scope) {
    $scope.__ = __;
    var vm = this;

    vm.findScope = function() {
      var parentScope = $scope;
      while (! parentScope.angularForm) {
        parentScope = parentScope.$parent;
      }
      return parentScope.angularForm;
    };

    vm.chooseValidation = function() {
      if (vm.restful) {
        vm.validate(
          {target: '.validate_button:visible'},
          vm.valtype,
          true,
          vm.findScope,
          vm.validateUrl,
        );
      } else {
        vm.validate(vm.validateUrl);
      }
    };
  }],
  templateUrl: '/static/verify-button.html.haml',
});

ManageIQ.angular.app.component('verifyButton', {
  bindings: {
    validate: '<',
    enabled: '<',
    validateUrl: '@',
    restful: '<',
    valtype: '<',
    buttonLabels: '<',
  },
  controllerAs: 'vm',
  controller: ['$scope', function($scope) {
    $scope.__ = __;
    var vm = this;

    vm.findScope = function() {
      var parentScope = $scope;
      while (! parentScope.angularForm) {
        parentScope = parentScope.$parent;
      }
      return parentScope.angularForm;
    };

    vm.chooseValidation = function() {
      if (vm.restful) {
        vm.validate(
          {target: '.validate_button:visible'},
          vm.valtype,
          true,
          vm.findScope,
          vm.validateUrl
        );
      } else {
        vm.validate(vm.validateUrl);
      }
    };
  }],
  templateUrl: '/static/verify-button.html.haml',
});

Remove trailing comma syntax error


var GameLayer = cc.Layer.extend({

	ctor:function () {
		//
		this._super();

		var gameLayer = ccs.load(res.GameScene_json);
		this.addChild(gameLayer.node)
	}
});

var GameScene = cc.Scene.extend({
	onEnter:function() {
		this._super();
		var layer = new GameLayer();
		this.addChild(layer);
	}
});

var GameLayer = cc.Layer.extend({

	ctor:function () {
		//
		this._super();

		var bkg = new cc.LayerColor(cc.color.WHITE);
		this.addChild(bkg);

		var gameLayer = ccs.load(res.GameScene_json);
		this.addChild(gameLayer.node);
	}
});

var GameScene = cc.Scene.extend({
	onEnter:function() {
		this._super();
		var layer = new GameLayer();
		this.addChild(layer);
	}
});

Add background for game scene


/*globals angular, console*/
/**
 * @author lattmann / https://github.com/lattmann
 */

angular.module('RequirementsApp').controller('SearchController', function (SearchService, $scope) {
    'use strict';

    var self = this;

    console.log('SearchController');

    $scope.model = {
        data: {}
    };

    $scope.search = function (search_query) {
        SearchService.search(search_query)
            .then(function (data) {
                // TODO: handle error here
                $scope.model.data = data;
                console.log(data);
            });
    };

});

/*globals angular, console*/
/**
 * @author lattmann / https://github.com/lattmann
 */

angular.module('RequirementsApp').controller('SearchController', function (SearchService, $scope, $location) {
    'use strict';

    var self = this;

    console.log('SearchController');

    $scope.model = {
        data: {}
    };
    $scope.search_query = $location.search().q;

    $scope.search = function (search_query) {

        $location.search('q', search_query);

        SearchService.search(search_query)
            .then(function (data) {
                // TODO: handle error here
                $scope.model.data = data;
                console.log(data);
            });
    };

    if ($scope.search_query) {
        $scope.search($scope.search_query);
    }

});

Update search query in the url.


/**
 * Ripple Client Configuration
 *
 * Copy this file to config.js and edit to suit your preferences.
 */
var Options = {
  server: {
    "trusted" : true,
    "websocket_ip" : "127.0.0.1",
    "websocket_port" : 5006,
    "websocket_ssl" : false
  },
  blobvault : "54.243.129.146:80",

  // If set, login will persist across sessions (page reload). This is mostly
  // intended for developers, be careful about using this in a real setting.
  persistent_auth : false
};

// Load client-side overrides
if (store.enabled) {
  $.extend(true, Options, JSON.parse(store.get('ripple_settings') || "{}"));
}

/**
 * Ripple Client Configuration
 *
 * Copy this file to config.js and edit to suit your preferences.
 */
var Options = {
  server: {
    "trusted" : true,
    "websocket_ip" : "s1.ripple.com",
    "websocket_port" : 51233,
    "websocket_ssl" : true
//    "websocket_ip" : "127.0.0.1",
//    "websocket_port" : 5006,
//    "websocket_ssl" : false
  },
  blobvault : "54.243.129.146:80",

  // If set, login will persist across sessions (page reload). This is mostly
  // intended for developers, be careful about using this in a real setting.
  persistent_auth : false
};

// Load client-side overrides
if (store.enabled) {
  $.extend(true, Options, JSON.parse(store.get('ripple_settings') || "{}"));
}

Add s1 as the default server in the example config.


module.exports = {
  parser: 'babel-eslint',
  extends: ['airbnb-base', 'prettier'],
  plugins: ['prettier'],
  globals: {
    Promise: true
  },
  env: {
    node: true
  },
  rules: {
    'comma-dangle': 'off',
    'import/prefer-default-export': ['warn'],
    'function-paren-newline': ['error', 'consistent'],
    'prettier/prettier': ['error', {
      'singleQuote': true,
      'parser': 'flow'
    }]
  }
};

module.exports = {
  parser: 'babel-eslint',
  extends: ['airbnb-base', 'prettier'],
  plugins: ['prettier'],
  globals: {
    Promise: true
  },
  env: {
    jest: true,  // https://stackoverflow.com/a/40265356/586382
    node: true
  },
  rules: {
    'comma-dangle': 'off',
    'import/prefer-default-export': ['warn'],
    'function-paren-newline': ['error', 'consistent'],
    'prettier/prettier': ['error', {
      'singleQuote': true,
      'parser': 'flow'
    }]
  }
};

Remove linting errors due to `jest` globals


import { combineReducers } from 'redux';
import { routerReducer } from 'react-router-redux';

const rootReducer = combineReducers({
    routing: routerReducer
});

export default rootReducer;

import { combineReducers } from 'redux';
import { routerReducer } from 'react-router-redux';
import { reducer as formReducer } from 'redux-form';

const rootReducer = combineReducers({
    form: formReducer,
    routing: routerReducer
});

export default rootReducer;

Create root reducer for the application


module.exports = {
  root: true,
  parser: 'babel-eslint',
  parserOptions: {
    sourceType: 'module'
  },
  // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style
  extends: 'standard',
  // required to lint *.vue files
  plugins: [
    'html'
  ],
  // add your custom rules here
  'rules': {
    // allow paren-less arrow functions
    'arrow-parens': 0,
    'key-spacing': 0,
    // allow async-await
    'generator-star-spacing': 0,
    // allow debugger during development
    'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0
  }
}

module.exports = {
  root: true,
  parser: 'babel-eslint',
  parserOptions: {
    sourceType: 'module'
  },
  // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style
  extends: 'standard',
  // required to lint *.vue files
  plugins: [
    'html'
  ],
  // add your custom rules here
  'rules': {
    // allow paren-less arrow functions
    'arrow-parens': 0,
    'key-spacing': 0,
    'no-multi-spaces': 0,
    // allow async-await
    'generator-star-spacing': 0,
    // allow debugger during development
    'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0
  }
}

Remove no-multi-spaces rule from eslint


'use strict';
var $ = require('jQuery');
var onReady = require('kwf/on-ready');
var BaseUrl = require('kwf/base-url');

onReady.onRender('.kwcClass', function(el) {
    //if embed template is used turn all xhr into cross domain xhr
    $.ajaxPrefilter(function(options) {
        if (options.url.substr(0, 1) == '/') {
            options.url = el.data('kwfUp-base-url')+options.url;
            options.withCredentials = true;
        }
    });
    BaseUrl.set(el.data('kwfUp-base-url'));
}, { priority: -10 });

'use strict';
var $ = require('jQuery');
var onReady = require('kwf/on-ready');
var BaseUrl = require('kwf/base-url');

onReady.onRender('.kwcClass', function(el) {
    //if embed template is used turn all xhr into cross domain xhr
    $.ajaxPrefilter(function(options) {
        if (options.url.substr(0, 1) == '/') {
            options.url = el.data('base-url')+options.url;
            options.withCredentials = true;
        }
    });
    BaseUrl.set(el.data('base-url'));
}, { priority: -10 });

Fix getting baseUrl from component-div


module.exports = {
  extends: 'fyndiq',
  rules: {
    // This rules causes issues because of nested packages.json, disabling
    'import/no-extraneous-dependencies': 0,
    'jsx-a11y/label-has-for': ['error', {
      required: {
        every: ['nesting'],
      },
    }],
  },
}

module.exports = {
  extends: 'fyndiq',
  rules: {
    // These rules causes issues because of nested packages.json, disabling
    'import/no-extraneous-dependencies': 0,
    'import/no-unresolved': [2, { ignore: ['@storybook/react'] }],
    'import/extensions': [2, { ignorePackages: true }],

    'jsx-a11y/label-has-for': ['error', {
      required: {
        every: ['nesting'],
      },
    }],
  },
}

Tweak eslint config to ignore problematic packages


module.exports = global.Promise

if (!module.exports) {
  try {
    module.exports = require('bluebird')
  } catch (_) {}
}

try {
  module.exports = require('bluebird')
} catch (_) {
  module.exports = global.Promise
}

Add attempt to require bluebird first


var Proxy = require('./proxy');
var RouterClient = require('./router_client');
var ServiceRegistryClient = require('./service_registry_client');
var VersionClient = require('./version_client');

var port = process.env.PORT || 4001;

var opts = {
  host: process.env.COREOS_PRIVATE_IPV4
};

var serviceRegistryClient = new ServiceRegistryClient(opts);

var routerClient = new RouterClient(opts);

var versionClient = new VersionClient(opts);

var proxy = new Proxy(serviceRegistryClient, routerClient, versionClient);
proxy.listen(port, function() {
  console.log('proxy listening on http://localhost:' + port);
});

['SIGINT', 'SIGTERM'].forEach(function(signal) {
  process.on(signal, function() {

    var count = proxy._peerSockets.length;
    proxy._peerSockets.forEach(function(peer) {
      routerClient.remove(peer.tenantId, peer.targetName, function() {
        count--;
        if (count === 0) {
          process.exit();
        }
      })
    });

    if (count === 0) {
      process.exit();
    }

  });
});

var Proxy = require('./proxy');
var RouterClient = require('./router_client');
var ServiceRegistryClient = require('./service_registry_client');
var VersionClient = require('./version_client');

var port = process.env.PORT || 4001;

var opts = {
  host: process.env.COREOS_PRIVATE_IPV4
};

// allow a list of peers to be passed, overides COREOS_PRIVATE_IPV4
if (process.env.ETCD_PEER_HOSTS) {
  opts.host = process.env.ETCD_PEER_HOSTS.split(',');
}

var serviceRegistryClient = new ServiceRegistryClient(opts);

var routerClient = new RouterClient(opts);

var versionClient = new VersionClient(opts);

var proxy = new Proxy(serviceRegistryClient, routerClient, versionClient);
proxy.listen(port, function() {
  console.log('proxy listening on http://localhost:' + port);
});

['SIGINT', 'SIGTERM'].forEach(function(signal) {
  process.on(signal, function() {

    var count = proxy._peerSockets.length;
    proxy._peerSockets.forEach(function(peer) {
      routerClient.remove(peer.tenantId, peer.targetName, function() {
        count--;
        if (count === 0) {
          process.exit();
        }
      })
    });

    if (count === 0) {
      process.exit();
    }

  });
});

Allow env option to pass in a list of etcd peers


//Source: http://stackoverflow.com/questions/3837037/div-with-scrollbar-inside-div-with-positionfixed
(function($) {
  $.fn.getPotentialHeight = function() {
        var $element = this;
        //heightOfParent is the height of parents content (inside the padding)
        var heightOfParent = $element.parent().height();
        var offset = $element.position();
        var topOfElement = offset.top;
        // potential height of element including the elements margin
        var phInclMargin = heightOfParent - topOfElement;
        // potential height of element excluding the elements margin
        var phExclMargin = phInclMargin - parseInt($element.css('margin-top')) - parseInt($element.css('margin-bottom'));
        return phExclMargin;
  };
})(jQuery);

$(document).ready(
    function() {
        $filterList = $('#filter-list');
        var phFilterList = $filterList.getPotentialHeight();
        $filterList.css('height', phFilterList);

        $infoWrapper = $('#info-wrapper');
        var phInfoWrapper = $infoWrapper.getPotentialHeight();
        $infoWrapper.css('height', phInfoWrapper);
    }
);

//Source: http://stackoverflow.com/questions/3837037/div-with-scrollbar-inside-div-with-positionfixed
(function($) {
  $.fn.getPotentialHeight = function() {
        var $element = this;
        //heightOfParent is the height of parents content (inside the padding)
        var heightOfParent = $element.parent().height();
        var offset = $element.position();
        var topOfElement = offset.top;
        // potential height of element including the elements margin
        var phInclMargin = heightOfParent - topOfElement;
        // potential height of element excluding the elements margin
        var phExclMargin = phInclMargin - parseInt($element.css('margin-top')) - parseInt($element.css('margin-bottom'));
        return phExclMargin;
  };
})(jQuery);

$(document).ready(
    function() {
        $filterList = $('#filter-list');
        var phFilterList = $filterList.getPotentialHeight();
        $filterList.css('height', phFilterList);

        $infoWrapper = $('#info-wrapper');
        var phInfoWrapper = $infoWrapper.getPotentialHeight();
        //$infoWrapper.css('height', phInfoWrapper);
    }
);

Set height info wrapper to 100%


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

var DtsBundlePlugin = require("./webpack.dts.plugin");

module.exports = {
    entry: {
        main: "./src/index",
    },

    resolve: {
        extensions: [".ts"],
    },

    output: {
        filename: "trapezium.js",
    },

    module: {
        rules: [
            /**
             * Enable inline source maps for code coverage report.
             *
             * See project repository for details / configuration reference:
             * https://github.com/s-panferov/awesome-typescript-loader
             */
            {
                test: /\.ts(x?)$/,
                use: [
                    "ts-loader",
                ],
            },
        ],
    },

    plugins: [
        new DtsBundlePlugin(),
    ],
};

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

var DtsBundlePlugin = require("./webpack.dts.plugin");

module.exports = {
    entry: {
        main: "./src/index",
    },

    resolve: {
        extensions: [".ts"],
    },

    output: {
        filename: "trapezium.js",
        libraryTarget: "commonjs",
    },

    module: {
        rules: [
            /**
             * Enable inline source maps for code coverage report.
             *
             * See project repository for details / configuration reference:
             * https://github.com/s-panferov/awesome-typescript-loader
             */
            {
                test: /\.ts(x?)$/,
                use: [
                    "ts-loader",
                ],
            },
        ],
    },

    plugins: [
        new DtsBundlePlugin(),
    ],
};

Add libraryTarget to make module exportable


const promise = require('bluebird');

const options = {
  promiseLib: promise
};

const pgp = require('pg-promise')(options);
const connectionString = 'postgres://localhost:5432/todos';
const db = pgp(connectionString);

let getAllTodos = (req, res, next) => {
  db.any('SELECT * FROM todos')
    .then(data => {
      res.status(200)
        .json({
          status: 'success',
          data: data,
          message: 'Retrieved ALL todos'
        });
    })
    .catch(err => {
      return next(err);
    });
}

module.exports = {
  getAllTodos: getAllTodos
};

Add function to get all todos


(function(win, doc, $, ko){

    var options = {
       hiddenClass: 'hidden'
    };

    ko.bindingHandlers.hint = {
        init:function (element, valueAccessor, allBindingsAccessor) {
            var observable = valueAccessor(),
                hintOptions = allBindingsAccessor().hintOptions,
                cssClass;

            if(hintOptions && hintOptions.hiddenClass){
                cssClass = hintOptions.hiddenClass;
            }else{
                cssClass = options.hiddenClass;
                insertCustomCss();
            }

            if (observable()) {
                $(element).removeClass(cssClass);
            } else {
                $(element).addClass(cssClass);
            }
        },

        update:function (element, valueAccessor, allBindingsAccessor) {
            var observable = valueAccessor(),
                hintOptions = allBindingsAccessor().hintOptions,
                cssClass;

            if(hintOptions && hintOptions.hiddenClass){
                cssClass = hintOptions.hiddenClass;
            }else{
                cssClass = options.hiddenClass;
            }

            if (observable()) {
                $(element).removeClass(cssClass);
            } else {
                $(element).addClass(cssClass);
            }
        }
    };

    function insertCustomCss(){
        var css = [
            '<style>',
            '.hidden{display: none !important;}',
            '</style>'
        ];

        doc.write(css.join(''));
    }

})(window,document, jQuery, ko);

(function(win, doc, $, ko){

    var options = {
       hiddenClass: 'hidden'
    };

    ko.bindingHandlers.hint = {
        init:function (element, valueAccessor, allBindingsAccessor) {
            var observable = valueAccessor(),
                hintOptions = allBindingsAccessor().hintOptions,
                cssClass;

            if(hintOptions && hintOptions.hiddenClass){
                cssClass = hintOptions.hiddenClass;
            }else{
                cssClass = options.hiddenClass;
                insertCustomCss();
            }

            applyHint(observable, element, cssClass);
        },

        update:function (element, valueAccessor, allBindingsAccessor) {
            var observable = valueAccessor(),
                hintOptions = allBindingsAccessor().hintOptions,
                cssClass;

            if(hintOptions && hintOptions.hiddenClass){
                cssClass = hintOptions.hiddenClass;
            }else{
                cssClass = options.hiddenClass;
            }

            applyHint(observable, element, cssClass);
        }
    };

    function applyHint(observable, element, cssClass){
        if (observable()) {
            $(element).removeClass(cssClass);
        } else {
            $(element).addClass(cssClass);
        }
    }

    function insertCustomCss(){
        var css = [
            '<style>',
            '.hidden{display: none !important;}',
            '</style>'
        ];

        doc.write(css.join(''));
    }

})(window,document, jQuery, ko);

Clean hint logic from copy/paste


import ContextualIdentities from '../ContextualIdentity';
import PreferenceGroup from './PreferenceGroup';
import ContainerPreference from './ContainerPreference';

/**
 * Contains a @see{ContainerPreference} for each existing container
 */
export default class ContainerPreferenceGroup extends PreferenceGroup {

  constructor({name, label, description}) {
    super({name, label, description, preferences: [], toggleable: false});
  }

  async fillContainer() {
    // Get all existing containers and create ContainerPref
    this._preferences = (await ContextualIdentities.get())
        .map((container) => {
          return new ContainerPreference({
            name: container.cookieStoreId,
            label: container.name,
          });
        });
    return super.fillContainer();
  }

  async updateFromDb() {
    return Promise.all(this._preferences.map((preference) => preference.updateFromDb()));
  }

}

ContainerPreferenceGroup.TYPE = 'containers';

import ContextualIdentities from '../ContextualIdentity';
import PreferenceGroup from './PreferenceGroup';
import ContainerPreference from './ContainerPreference';

/**
 * Contains a @see{ContainerPreference} for each existing container
 */
export default class ContainerPreferenceGroup extends PreferenceGroup {

  constructor({name, label, description}) {
    super({name, label, description, preferences: [], toggleable: false});
  }

  async fillContainer() {
    // Get all existing containers and create ContainerPref
    this._preferences = (await ContextualIdentities.get())
        .map((container) => {
          return new ContainerPreference({
            name: `${this.name}.${container.cookieStoreId}`,
            label: container.name,
          });
        });
    return super.fillContainer();
  }

  async updateFromDb() {
    return Promise.all(this._preferences.map((preference) => preference.updateFromDb()));
  }

}

ContainerPreferenceGroup.TYPE = 'containers';

Use the correct variable for ContainerPreference names


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

module.exports = {
  pure : function(x){ return new Identity(x); },
  copure : function(idx){ return idx.val; }
}

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

module.exports = {
  pure : function(x){ return new Identity(x); },
  copure : function(idx){
    if(!(idx instanceof Identity && idx.type === 'Identity')){
      throw new Error('Expected type Identity in first argument of MonadIdentity.copure, but got ' + typeof idx);
    }
    return idx.val;
  }
}

Add error detection in Identity.cobind


'use babel';

import { CompositeDisposable } from 'atom';
import fs from 'fs';

export default {
  modalPanel: null,
  subscriptions: null,

  config: {
    shouldCreateFile: {
      type: 'boolean',
      default: true,
    },
    testExtension: {
      type: 'string',
      default: '.spec',
    },
  },

  activate(state) {
    this.subscriptions = new CompositeDisposable();
    this.subscriptions.add(atom.commands.add('atom-workspace', {
      'open-tests:open': () => this.open()
    }));
  },

  deactivate() {
    this.subscriptions.dispose();
  },

  open() {
    const testExtension = atom.config.get('open-tests.testExtension')
    const shouldCreate = atom.config.get('open-tests.shouldCreateFile')

    const filePath = atom.workspace.getActivePaneItem().buffer.file.path

    const index = filePath.lastIndexOf('.')
    const fileExtension = filePath.substring(index)
    const fileWithoutExt = filePath.substring(0,index)

    const testPath = fileWithoutExt + testExtension + fileExtension

    if (!fs.existsSync(path) && !shouldCreate) {
      atom.notifications.addError('File not found')
      return
    }

    atom.open({ pathsToOpen: testPath })
  }
};

'use babel';

import { CompositeDisposable } from 'atom';
import fs from 'fs';

export default {
  modalPanel: null,
  subscriptions: null,

  config: {
    shouldCreateFile: {
      type: 'boolean',
      default: true,
    },
    testExtension: {
      type: 'string',
      default: '.spec',
    },
  },

  activate(state) {
    this.subscriptions = new CompositeDisposable();
    this.subscriptions.add(atom.commands.add('atom-workspace', {
      'open-tests:open': () => this.open()
    }));
  },

  deactivate() {
    this.subscriptions.dispose();
  },

  getTestPath() {
    const testExtension = atom.config.get('open-tests.testExtension')
    const filePath = atom.workspace.getActivePaneItem().buffer.file.path

    const index = filePath.lastIndexOf('.')
    const fileExtension = filePath.substring(index)
    const fileWithoutExt = filePath.substring(0,index)

    return (fileWithoutExt + testExtension + fileExtension)
  },

  open() {
    const shouldCreate = atom.config.get('open-tests.shouldCreateFile')

    const testPath = getTestPath()

    if (!fs.existsSync(path) && !shouldCreate) {
      atom.notifications.addError('File not found')
      return
    }

    atom.open({ pathsToOpen: testPath })
  }
};

Split code in separate function


import React from 'react'

export const ResumeIcon = ({ className, ...props }) => (
  <svg
    {...props}
    className={`text-resume ${className}`}
    role="img"
    fill="none"
    stroke="currentColor"
    viewBox="0 0 24 24"
    xmlns="http://www.w3.org/2000/svg"
  >
    <title>Resume</title>

    <path
      strokeLinecap="round"
      strokeLinejoin="round"
      strokeWidth="2"
      d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
    ></path>
  </svg>
)

import React from 'react'

export const ResumeIcon = ({ className, ...props }) => (
  <svg
    {...props}
    className={`text-resume ${className}`}
    role="img"
    fill="none"
    stroke="currentColor"
    viewBox="0 0 24 24"
    xmlns="http://www.w3.org/2000/svg"
  >
    <title>Resume PDF</title>

    <path
      strokeLinecap="round"
      strokeLinejoin="round"
      strokeWidth="2"
      d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
    ></path>
  </svg>
)

Change PDF to icon title


import Ember from 'ember';
import Application from '../../app';
import config from '../../config/environment';

export default function startApp(attrs) {
  let application;

  // use defaults, but you can override
  let attributes = Ember.assign({}, config.APP, attrs);

  Ember.run(() => {
    application = Application.create(attributes);
    application.setupForTesting();
    application.injectTestHelpers();
  });

  return application;
}

import Ember from 'ember';
import Application from '../../app';
import config from '../../config/environment';

export default function startApp(attrs) {
  let application;

  let attributes = Ember.merge({}, config.APP);
  attributes = Ember.merge(attributes, attrs); // use defaults, but you can override;

  Ember.run(() => {
    application = Application.create(attributes);
    application.setupForTesting();
    application.injectTestHelpers();
  });

  return application;
}

Fix Ember 2.4 test failures


module.exports = require('xmlbuilder');
module.exports.XMLFragment = require('xmlbuilder/lib/XMLFragment');

module.exports.XMLFragment.prototype.addFragment = function(fragment) {
  fragment.parent = this;
  this.children.push(fragment);
  return this;
};

// This is a workaround for the problem that text() does not work when empty string is given.
// https://github.com/oozcitak/xmlbuilder-js/pull/19
var originalToString = module.exports.XMLFragment.prototype.toString;
module.exports.XMLFragment.prototype.toString = function() {
  var string = originalToString.apply(this, arguments);
  return string.replace(/<\/>/g, '');
};

module.exports = require('xmlbuilder');
module.exports.XMLFragment = require('xmlbuilder/lib/XMLFragment');

module.exports.XMLFragment.prototype.addFragment = function(fragments) {
  if (fragments) {
    if (!Array.isArray(fragments))
      fragments = [fragments];
    fragments.forEach(function(fragment) {
      fragment.parent = this;
      this.children.push(fragment);
    }, this);
  }
  return this;
};

// This is a workaround for the problem that text() does not work when empty string is given.
// https://github.com/oozcitak/xmlbuilder-js/pull/19
var originalToString = module.exports.XMLFragment.prototype.toString;
module.exports.XMLFragment.prototype.toString = function() {
  var string = originalToString.apply(this, arguments);
  return string.replace(/<\/>/g, '');
};

Support null and array for addFragment()


// Write a test that validates that a new role created has a unique title.
// Write a test that validates that all roles are returned when Roles.all is called.

'use strict';

const expect    = require('chai').expect;
const supertest = require('supertest');
const server    = require('./../../index');
const api       = supertest(server);

describe('Roles', () => {
  it('each role should have a unique title', (done) => {
    done();
  });

  it('should return all roles when Roles.all is called', (done) => {
    done();
  });
});

Implement basic tests for roles


(function() {
    'use strict';

    angular.module('app.controllers.channels', []).
        controller('Channels', Channels);

    Channels.$inject = ['$rootScope', 'chat'];
    function Channels($rootScope, chat) {
        var vm = this;

        $rootScope.selected = '#roomtest';
        vm.select = function(channel) {
            console.log(channel);
            vm.selected = channel;

            $rootScope.selected = channel;
        };

        vm.add = function() {
            vex.dialog.prompt({
                message: 'What planet did the aliens come from?',
                placeholder: 'Planet name',
                callback: function(value) {
                    if (!value) {
                        return;
                    }

                    $rootScope.logs[value] = [];

                    chat.scrollback(value);

                    vm.select(value);

                    chat.join(value);

                    return console.log(value);
                }
            });
        };
    }
})();

(function() {
    'use strict';

    angular.module('app.controllers.channels', []).
        controller('Channels', Channels);

    Channels.$inject = ['$rootScope', 'chat'];
    function Channels($rootScope, chat) {
        var vm = this;

        $rootScope.selected = '#roomtest';
        vm.select = function(channel) {
            console.log(channel);
            vm.selected = channel;

            $rootScope.selected = channel;
        };

        vm.add = function() {
            vex.dialog.prompt({
                message: 'What channel do you want to join?',
                placeholder: 'Channel name #...',
                callback: function(value) {
                    if (!value) {
                        return;
                    }

                    $rootScope.logs[value] = [];

                    chat.scrollback(value);

                    vm.select(value);

                    chat.join(value);

                    return console.log(value);
                }
            });
        };
    }
})();

Fix vex dialog being off topic


module.exports = function(app) {
  require('./storage/url')(app);
};

module.exports = function(app) {
  require('./storage/url')(app);
  require('./storage/s3')(app);
  require('./storage/dropbox')(app);
};

Add links to storage providers.


'use strict';

const api = require('api');

const router = require('koa-router')();

router.get('/search/em', function*() {
    const value = +this.query.value;
    if (!value) {
        return error(this, 'missing value');
    }
    const options = {};
    if (this.query.limit) options.limit = +this.query.limit;
    if (this.query.precision) options.precision = +this.query.precision;
    this.body = {
        result: yield api.search.em(value, options)
    };
});

router.get('/molecules/em', function*() {
    const value = +this.query.value;
    if (!value) {
        return error(this, 'missing value');
    }
    this.body = {
        result: yield api.molecules.em(value)
    };
});

router.get('/molecules/mf', function*() {
    const value = +this.query.value;
    if (!value) {
        return error(this, 'missing value');
    }
    this.body = {
        result: yield api.molecules.mf(value)
    };
});

function error(ctx, message) {
    ctx.status = 400;
    ctx.body = {
        error: message
    };
}

module.exports = router;

'use strict';

const api = require('api');

const router = require('koa-router')();

router.get('/search/em', function*() {
    const value = +this.query.value;
    if (!value) {
        return error(this, 'missing value');
    }
    const options = {};
    if (this.query.limit) options.limit = +this.query.limit;
    if (this.query.precision) options.precision = +this.query.precision;
    this.body = {
        result: yield api.search.em(value, options)
    };
});

router.get('/molecules/em', function*() {
    const value = +this.query.value;
    if (!value) {
        return error(this, 'missing value');
    }
    this.body = {
        result: yield api.molecules.em(value)
    };
});

router.get('/molecules/mf', function*() {
    const value = this.query.value;
    if (!value) {
        return error(this, 'missing value');
    }
    this.body = {
        result: yield api.molecules.mf(value)
    };
});

function error(ctx, message) {
    ctx.status = 400;
    ctx.body = {
        error: message
    };
}

module.exports = router;

Add route for molecule mf


var express = require('express')
	, app = express()
	, http = require('http').Server(app)
	, Q = require('q');

var ROOT = GLOBAL.proj_root
	, SENDFILE_OPTS = { root: ROOT }
	, PORT = 55221
	, START_TIMEOUT = 5;

// Static content
app.use('/components', express.static(ROOT + '/components'));
app.use('/dist', express.static(ROOT + '/dist'));
app.use('/fonts', express.static(ROOT + '/fonts'));
app.get('/', function(req, res) {
	res.sendFile('atom-app.html', SENDFILE_OPTS);
});

// App routes
require('./routes')(app);

module.exports = {
	start: function startServer() {
		return Q.promise(function(resolve, reject) {
			var timeout = setTimeout(function() {
				reject('Server did not start within ' + START_TIMEOUT + ' seconds');
			}, START_TIMEOUT * 1000);

			http.listen(PORT, function() {
				clearTimeout(timeout);
				console.log('Server listening on port %s', PORT);
				resolve(http);
			});
		});
	}
}

var express = require('express')
	, app = express()
	, http = require('http').Server(app)
	, Q = require('q');

var ROOT = GLOBAL.proj_root
	, SENDFILE_OPTS = { root: ROOT }
	, PORT = 55221
	, START_TIMEOUT = 5;

// Static content
app.use('/components', express.static(ROOT + '/components'));
app.use('/dist', express.static(ROOT + '/dist'));
app.use('/fonts', express.static(ROOT + '/fonts'));
app.get('/', function(req, res) {
	res.sendFile('atom-app.html', SENDFILE_OPTS);
});

// App routes
require('./routes')(app);

module.exports = {
	start: function startServer() {
		return Q.promise(function(resolve, reject) {
			var timeout = setTimeout(function() {
				reject('Server did not start within ' + START_TIMEOUT + ' seconds');
			}, START_TIMEOUT * 1000);

			http.listen(PORT, 'localhost');
			http.on('listening', function() {
				clearTimeout(timeout);
				console.log('Server listening on port %s', PORT);
				resolve(http);
			});
		});
	}
}

Make http server listen only on localhost


var scripts = document.getElementsByTagName('script'),
    script = scripts[scripts.length - 1],
    report = JSON.parse(script.getAttribute('data-report')),
    type = script.getAttribute('data-type');

google.load('visualization', '1.0', {'packages':['corechart']});
google.setOnLoadCallback(drawChart);

function drawChart() {
    if(report.length > 1) {
        var chart_height = (report.length - 1) * 20,
            reverse = type === 'week' ? true : false,
            wrapper = new google.visualization.ChartWrapper({
            chartType: 'BarChart',
            dataTable: google.visualization.arrayToDataTable(report),
            options: {
                chartArea: {
                    bottom: 50,
                    height: chart_height,
                    left: '10%',
                    right: '10%',
                    top: 50,
                    width: '90%'
                },
                height: chart_height + 100,
                legend: {
                    alignment: 'center',
                    position: 'top'
                },
                reverseCategories: reverse
            },
            containerId: 'chart'
        });
        wrapper.draw();
    } else {
        container = $('#chart');
        container.text('');
    }
}

var scripts = document.getElementsByTagName('script'),
    script = scripts[scripts.length - 1],
    report = JSON.parse(script.getAttribute('data-report')),
    type = script.getAttribute('data-type');

google.load('visualization', '1.0', {'packages':['corechart']});
google.setOnLoadCallback(drawChart);

function drawChart() {
    if(report.length > 1) {
        var chart_height = (report.length - 1) * 20,
            reverse = type === 'week' ? true : false,
            wrapper = new google.visualization.ChartWrapper({
            chartType: 'BarChart',
            dataTable: google.visualization.arrayToDataTable(report),
            options: {
                chartArea: {
                    bottom: 50,
                    height: chart_height,
                    left: '10%',
                    right: '10%',
                    top: 50,
                    width: '90%'
                },
                height: chart_height + 100,
                legend: {
                    alignment: 'center',
                    position: 'top'
                },
                reverseCategories: reverse
            },
            containerId: 'chart'
        });
        wrapper.draw();
    } else if (report.length === 1) {
        var container = $('#chart'),
            text = $('
No data to display.
');
        container.append(text);
    }
}

Use default text when no data exists for query


const express = require('express')
const app = express()
const path = require('path')
const nunjucks = require('nunjucks')

module.exports = app

// Set up App
const appViews = [
  path.join(__dirname, '/app/views/'),
  path.join(__dirname, '/app/templates/')
]

nunjucks.configure(appViews, {
  autoescape: true,
  express: app,
  noCache: true,
  watch: true
})

// Set views engine
app.set('view engine', 'html')

// Serve static content for the app from the "public" directory
app.use('/public', express.static(path.join(__dirname, '/public')))

// Send assetPath to all views
app.use(function (req, res, next) {
  res.locals.asset_path = '/public/'
  next()
})

// Render views/index
app.get('/', function (req, res) {
  res.render('index')
})

// Log when app is running
app.listen(3000, function () {
  console.log('GOV.UK Frontend Alpha\n')
  console.log('Listening on port 3000   url: http://localhost:3000')
})

const express = require('express')
const app = express()
const path = require('path')
const nunjucks = require('nunjucks')

module.exports = app

// Set up App
const appViews = [
  path.join(__dirname, '/app/views/'),
  path.join(__dirname, '/app/templates/'),
  path.join(__dirname, '/app/components/')
]

nunjucks.configure(appViews, {
  autoescape: true,
  express: app,
  noCache: true,
  watch: true
})

// Set views engine
app.set('view engine', 'html')

// Serve static content for the app from the "public" directory
app.use('/public', express.static(path.join(__dirname, '/public')))

// Send assetPath to all views
app.use(function (req, res, next) {
  res.locals.asset_path = '/public/'
  next()
})

// Render views/index
app.get('/', function (req, res) {
  res.render('index')
})

// Log when app is running
app.listen(3000, function () {
  console.log('GOV.UK Frontend Alpha\n')
  console.log('Listening on port 3000   url: http://localhost:3000')
})

Configure app to include a components folder


/**
 *
 */

$(document).ready(function() {
	var processCheckerUrl = 'AlignmentChecker?id=' + getUrlParameter('id');

	(function poll() {
		$.ajax({
			url : processCheckerUrl,
			type: "GET",
			success : function(responseText) {
				// TODO - redirect to correct page
				var redirectUrl = 'AligmentResultServlet?id=' + getUrlParameter('id');
				window.location.href = redirectUrl;
			},
			error: function(){
				// TODO - manage errors
	            alert("Processes doesn't exists");
	        },

	        // Polling: http://stackoverflow.com/questions/6835835/jquery-simple-polling-example
			complete: setTimeout(function() {poll()}, 5000),
	        timeout: 2000,
		});
	})();

});

// http://stackoverflow.com/a/21903119
function getUrlParameter(sParam)
{
    var sPageURL = window.location.search.substring(1);
    var sURLVariables = sPageURL.split('&');
    for (var i = 0; i < sURLVariables.length; i++)
    {
        var sParameterName = sURLVariables[i].split('=');
        if (sParameterName[0] == sParam)
        {
            return sParameterName[1];
        }
    }
}

/**
 *
 */

$(document).ready(function() {
	var processCheckerUrl = 'AlignmentChecker?id=' + getUrlParameter('id');

	(function poll() {
		$.ajax({
			url : processCheckerUrl,
			type: "GET",
			statusCode: {
			      200: function (responseText) {
			    	// TODO - redirect to correct page
			    	 var redirectUrl = 'AligmentResultServlet?id=' + getUrlParameter('id');
			    	 window.location.href = redirectUrl;
			      },
			   },
			error: function(){
				// TODO - manage errors
	            alert("Processes doesn't exists");
	        },

	        // Polling: http://stackoverflow.com/questions/6835835/jquery-simple-polling-example
			complete: setTimeout(function() {poll()}, 5000),
	        timeout: 2000,
		});
	})();

});

// http://stackoverflow.com/a/21903119
function getUrlParameter(sParam)
{
    var sPageURL = window.location.search.substring(1);
    var sURLVariables = sPageURL.split('&');
    for (var i = 0; i < sURLVariables.length; i++)
    {
        var sParameterName = sURLVariables[i].split('=');
        if (sParameterName[0] == sParam)
        {
            return sParameterName[1];
        }
    }
}

Manage only 200 success answer for show results


import {applyMiddleware, compose, createStore as rawCreateStore} from 'redux';
import {persistStore, autoRehydrate} from 'redux-persist';
import createSagaMiddleware from 'redux-saga';
import createRootReducer from './createRootReducer';
import rootSaga from './rootSaga';
import {APP_NAME} from '../modules/common/constants';

/**
 * @returns {function}
 */
export const createStore = () =>
  new Promise((resolve) => {
    const rootReducer = createRootReducer();
    const sagaMiddleware = createSagaMiddleware();
    const middlewares = [];

    middlewares.push(sagaMiddleware);

    const enhancer = compose(
      applyMiddleware(...middlewares),
      autoRehydrate(),
      window.devToolsExtension ? window.devToolsExtension() : (f) => f
    );

    const store = rawCreateStore(rootReducer, enhancer);

    // The promise returned by "createStore" will be resolved once we have re-hydrated the state.
    persistStore(store, {
      whitelist: [],
      blacklist: [],
      keyPrefix: `${APP_NAME}:`
    }, () => resolve(store));

    sagaMiddleware.run(rootSaga);

    if (__DEV__ && module.hot) {
      module.hot.accept('./createRootReducer', () => {
        const newRootReducer = require('./createRootReducer').default();
        store.replaceReducer(newRootReducer);
      });
    }
  });

export default createStore;

import {applyMiddleware, compose, createStore as rawCreateStore} from 'redux';
import {persistStore, autoRehydrate} from 'redux-persist';
import createSagaMiddleware from 'redux-saga';
import createRootReducer from './createRootReducer';
import rootSaga from './rootSaga';
import {APP_NAME} from '../modules/common/constants';

/**
 * @returns {function}
 */
export const createStore = () =>
  new Promise((resolve) => {
    const rootReducer = createRootReducer();
    const sagaMiddleware = createSagaMiddleware();
    const middlewares = [];

    middlewares.push(sagaMiddleware);

    const enhancer = compose(
      applyMiddleware(...middlewares),
      autoRehydrate(),
      window.devToolsExtension ? window.devToolsExtension() : (f) => f
    );

    const store = rawCreateStore(rootReducer, enhancer);

    // The promise returned by "createStore" will be resolved once we have re-hydrated the state.
    persistStore(store, {
      whitelist: ['language'],
      blacklist: [],
      keyPrefix: `${APP_NAME}:`
    }, () => resolve(store));

    sagaMiddleware.run(rootSaga);

    if (__DEV__ && module.hot) {
      module.hot.accept('./createRootReducer', () => {
        const newRootReducer = require('./createRootReducer').default();
        store.replaceReducer(newRootReducer);
      });
    }
  });

export default createStore;

Add persist language in local storage


import React from 'react';
import VideoListItem from './video_list_item';

const VideoList = (props) => {
  const videoItems = props.videos.map((video) => {
    return <VideoListItem video = {video} />
  });

  return (
    <ul className="col-md-4 list-group">
      {videoItems}
    </ul>
  );
}

export default VideoList;

import React from 'react';
import VideoListItem from './video_list_item';

const VideoList = (props) => {
  const videoItems = props.videos.map((video) => {
    return <VideoListItem key={video.etag} video={video} />
  });

  return (
    <ul className="col-md-4 list-group">
      {videoItems}
    </ul>
  );
}

export default VideoList;

Add keys to each video item


const env = process.env;

export const nodeEnv = env.NODE_ENV || 'development';

export default {
  port: env.PORT || 3001,
  host: env.HOST || '0.0.0.0',
  get serverUrl() {
    return `http://${this.host}:${this.port}`;
  }
};

const env = process.env;

export const nodeEnv = env.NODE_ENV || 'development';

export default {
  port: env.API_PORT || 3001,
  host: env.API_HOST || '0.0.0.0',
  get serverUrl() {
    return (typeof window === 'undefined') ? `http://${this.host}:${this.port}` : '';
  }
};

Update server: split api & app


import React from 'react';
import {
  BrowserRouter as Router,
  Route,
  Switch
} from 'react-router-dom';
import { NavigationBar } from '../NavigationBar';
import { PageHome } from '../PageHome';
import { PageLogin } from '../PageLogin';
import { NoRouteMatch } from '../NoRouteMatch';

const PageRouter = () => (
    <Router>
        <div>
            <NavigationBar />

            <Switch>
                <Route exact path="/" component={PageHome}/>
                <Route path="/login" component={PageLogin}/>
                <Route component={NoRouteMatch}/>
            </Switch>
        </div>
    </Router>
)

export { PageRouter };

import React from 'react';
import {
  BrowserRouter as Router,
  Route,
  Switch
} from 'react-router-dom';
import firebase from 'firebase';
import { NavigationBar } from '../NavigationBar';
import { PageHome } from '../PageHome';
import { PageLogin } from '../PageLogin';
import { NoRouteMatch } from '../NoRouteMatch';

class PageRouter extends React.Component {
    componentDidMount() {
        firebase.auth().onAuthStateChanged( user => {
            if ( user ) {
                //
            } else {
                //
            }
        });
    }
    render() {
        return (
            <Router>
                <div>
                    <NavigationBar />

                    <Switch>
                        <Route exact path="/" component={PageHome}/>
                        <Route path="/login" component={PageLogin}/>
                        <Route component={NoRouteMatch}/>
                    </Switch>
                </div>
            </Router>
        );
    }
}

export { PageRouter };

Add firebase auth event listener


/**
 * @license
 * Copyright 2017 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  refines: 'foam.core.Requires',
  flags: ['swift'],
  requires: [
    'foam.swift.Argument',
    'foam.swift.Method',
  ],
  properties: [
    {
      name: 'swiftReturns',
      expression: function(path) {
        return this.lookup(path).model_.swiftName;
      },
    },
  ],
  methods: [
    function writeToSwiftClass(cls, parentCls) {
      if ( ! parentCls.hasOwnAxiom(this.name) ) return;
      if (foam.core.InterfaceModel.isInstance(this.lookup(this.path).model_)) {
        return;
      }
      // TODO skip refines.
      cls.methods.push(this.Method.create({
        name: this.name + '_create',
        returnType: this.swiftReturns,
        visibility: 'public',
	body: this.swiftInitializer(),
        args: [
          this.Argument.create({
            localName: 'args',
            defaultValue: '[:]',
            type: '[String:Any?]',
          }),
        ],
      }));
    },
  ],
  templates: [
    {
      name: 'swiftInitializer',
      args: [],
      template: function() {/*
return __subContext__.create(<%=this.swiftReturns%>.self, args: args)!
      */},
    },
  ],
});

/**
 * @license
 * Copyright 2017 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

foam.CLASS({
  refines: 'foam.core.Requires',
  flags: ['swift'],
  requires: [
    'foam.swift.Argument',
    'foam.swift.Method',
  ],
  properties: [
    {
      name: 'swiftReturns',
      expression: function(path) {
        return this.lookup(path).model_.swiftName;
      },
    },
  ],
  methods: [
    function writeToSwiftClass(cls, parentCls) {
      if ( ! parentCls.hasOwnAxiom(this.name) ) return;
      if (foam.core.InterfaceModel.isInstance(this.lookup(this.path).model_)) {
        return;
      }
      // TODO skip refines.
      cls.methods.push(this.Method.create({
        name: this.name + '_create',
        returnType: this.swiftReturns,
        visibility: 'public',
	body: this.swiftInitializer(),
        args: [
          this.Argument.create({
            localName: 'args',
            defaultValue: '[:]',
            type: '[String:Any?]',
          }),
          this.Argument.create({
            localName: 'x',
            defaultValue: 'nil',
            type: 'Context?',
          }),
        ],
      }));
    },
  ],
  templates: [
    {
      name: 'swiftInitializer',
      args: [],
      template: function() {/*
return (x ?? __subContext__).create(<%=this.swiftReturns%>.self, args: args)!
      */},
    },
  ],
});

Add 2nd parameter to create that's generated for requires that allows you to overwrite context.


/* eslint-env mocha */
const gcd = require('../../../src').algorithms.math.gcd;

const assert = require('assert');

describe('GCD', () => {
  it('should return 0 for either or both numbers as 0', () => {
    assert.equal(gcd(0, 10), 0);
    assert.equal(gcd(10, 0), 0);
    assert.equal(gcd(0, 0), 0);
  });

  it('should return 1 for 1 and positive numbers >= 1', () => {
    assert.equal(gcd(1, 10), 1);
    assert.equal(gcd(1, 1), 1);
    assert.equal(gcd(10, 1), 1);
  });

  it('should return gcd of two numbers', () => {
    assert.equal(gcd(60, 10), 10);
    assert.equal(gcd(65, 10), 5);
    assert.equal(gcd(3, 2), 1);
  });
});

/* eslint-env mocha */
const gcd = require('../../../src').algorithms.math.gcd;

const assert = require('assert');

describe('GCD', () => {
  it('should return 0 for either or both numbers as 0', () => {
    assert.equal(gcd(0, 10), 0);
    assert.equal(gcd(10, 0), 0);
    assert.equal(gcd(0, 0), 0);
  });

  it('should return 1 for 1 and positive numbers >= 1', () => {
    assert.equal(gcd(1, 10), 1);
    assert.equal(gcd(1, 1), 1);
    assert.equal(gcd(10, 1), 1);
  });

  it('should return gcd of two numbers', () => {
    assert.equal(gcd(60, 10), 10);
    assert.equal(gcd(65, 10), 5);
    assert.equal(gcd(3, 2), 1);
  });

  it('should return gcd of negative numbers', () => {
    assert.equal(gcd(-60, -10), 10);
    assert.equal(gcd(65, -10), 5);
    assert.equal(gcd(-3, 2), 1);
  });
});

Test GCD: Tests handling of negative numbers


// imports
var gulp = require('gulp');
var browserify  = require('browserify');
var source      = require('vinyl-source-stream');
var uglify = require('gulp-uglify');
var buffer      = require('vinyl-buffer');

// build src
gulp.task('browserify', function(cb){
 	return browserify('./src/app.js', {
            debug: true
        })
        .bundle()
        .pipe(source('bundle.js'))
        .pipe(gulp.dest('./www/'));

    cb();
});

// build in release mode
gulp.task('browserify:release', function(cb){

 	return browserify('./src/app.js')
        .bundle()
        .pipe(source('bundle.js'))
        .pipe(buffer())
        .pipe(uglify())
        .pipe(gulp.dest('./www/'));

    cb();
});

// copy fonts
gulp.task('fonts', function(cb){
 	return gulp.src('node_modules/ionic-framework/release/fonts/**')
        .pipe(gulp.dest('./www/fonts/'));
    cb();
});

// copy assets
gulp.task('assets', function(cb){
 	return gulp.src('./assets/**')
        .pipe(gulp.dest('./www/'));
    cb();
});

// copy templates
gulp.task('templates', function(cb){
    return gulp.src('./src/**/*.html')
        .pipe(gulp.dest('./www/'));
    cb();
});

// imports
var gulp = require('gulp');
var browserify  = require('browserify');
var source      = require('vinyl-source-stream');
var uglify = require('gulp-uglify');
var buffer      = require('vinyl-buffer');

// build src
gulp.task('browserify', function(cb){
 	return browserify('./src/app.js', {
            debug: true
        })
        .bundle()
        .pipe(source('bundle.js'))
        .pipe(gulp.dest('./www/'));

    cb();
});

// build in release mode
gulp.task('browserify:release', function(cb){

 	return browserify('./src/app.js')
        .bundle()
        .pipe(source('bundle.js'))
        .pipe(buffer())
        .pipe(uglify())
        .pipe(gulp.dest('./www/'));

    cb();
});

// copy fonts
gulp.task('fonts', function(cb){
 	return gulp.src('node_modules/ionic-npm/fonts/**')
        .pipe(gulp.dest('./www/fonts/'));
    cb();
});

// copy assets
gulp.task('assets', function(cb){
 	return gulp.src('./assets/**')
        .pipe(gulp.dest('./www/'));
    cb();
});

// copy templates
gulp.task('templates', function(cb){
    return gulp.src('./src/**/*.html')
        .pipe(gulp.dest('./www/'));
    cb();
});

Update path fonts gulp task


import { forEach } from 'lodash-es';
import { RECEIVE_WIKIDATA_LABELS } from '../constants';

const initialState = {
  labels: {}
};

export default function wikidataLabels(state = initialState, action) {
  switch (action.type) {
    case RECEIVE_WIKIDATA_LABELS: {
      const newLabels = { ...state.labels };
      forEach(action.data.entities, (entity) => {
        const label = entity.labels[action.language] || entity.labels.en;
        if (!label) { return; }
        newLabels[entity.id] = label.value;
      });
      return { labels: newLabels };
    }
    default:
      return state;
  }
}

import { forEach } from 'lodash-es';
import { RECEIVE_WIKIDATA_LABELS } from '../constants';

const initialState = {
  labels: {}
};

export default function wikidataLabels(state = initialState, action) {
  switch (action.type) {
    case RECEIVE_WIKIDATA_LABELS: {
      const newLabels = { ...state.labels };
      forEach(action.data.entities, (entity) => {
        if (!entity.labels) { return; }
        const label = entity.labels[action.language] || entity.labels.en;
        if (!label) { return; }
        newLabels[entity.id] = label.value;
      });
      return { labels: newLabels };
    }
    default:
      return state;
  }
}

Fix error caused by a deleted Wikidata item


// ==========================================================================
// Project:   SproutCore Handlebar Views
// Copyright: ©2011 Strobe Inc. and contributors.
// License:   Licensed under MIT license (see license.js)
// ==========================================================================

require("sproutcore-views/views/view");
require("sproutcore-handlebars/ext");

var set = SC.set, get = SC.get;

// TODO: Be explicit in the class documentation that you
// *MUST* set the value of a checkbox through SproutCore.
// Updating the value of a checkbox directly via jQuery objects
// will not work.

SC.Checkbox = SC.View.extend({
  title: null,
  value: false,

  classNames: ['sc-checkbox'],

  defaultTemplate: SC.Handlebars.compile('<label><input type="checkbox" {{bindAttr checked="value"}}>{{title}}</label>'),

  click: function() {
    if (jQuery.browser.msie) {
      this.change();
    }
  },

  change: function() {
    SC.run.once(this, this._updateElementValue);
    return false;
  },

  _updateElementValue: function() {
    var input = this.$('input:checkbox');
    set(this, 'value', input.prop('checked'));
  }
});

// ==========================================================================
// Project:   SproutCore Handlebar Views
// Copyright: ©2011 Strobe Inc. and contributors.
// License:   Licensed under MIT license (see license.js)
// ==========================================================================

require("sproutcore-views/views/view");
require("sproutcore-handlebars/ext");

var set = SC.set, get = SC.get;

// TODO: Be explicit in the class documentation that you
// *MUST* set the value of a checkbox through SproutCore.
// Updating the value of a checkbox directly via jQuery objects
// will not work.

SC.Checkbox = SC.View.extend({
  title: null,
  value: false,

  classNames: ['sc-checkbox'],

  defaultTemplate: SC.Handlebars.compile('<label><input type="checkbox" {{bindAttr checked="value"}}>{{title}}</label>'),

  click: function() {
    SC.run.once(this, this._updateElementValue);
  },

  _updateElementValue: function() {
    var input = this.$('input:checkbox');
    set(this, 'value', input.prop('checked'));
  }
});

Fix SC.Checkbox bug in IE


import JobProvider from './jobProvider'

export default class extends JobProvider {
  constructor() {
    super({
      id: 'dmtk',
      name: 'domestika.org',
      logo: 'http://4.bp.blogspot.com/-_ntAal9lU2I/T3XBljnauCI/AAAAAAAAAWo/kS3eJcZZQvs/s490/domestika-logo.gif',
      scope: 'ul.jobs-list li.job-item',
      selectors: {
        title: 'h2.job-item__title a',
        url: '.h2.job-item__title a@href',
        date: 'div.job-item__date',
        company: 'h3.job-item__company',
        location: 'div.job-item__city',
        description: 'p.job-item__excerpt'
      }
    })
  }

  refine(item) {
    item.location = this.clean(item.location)
  }
}

import JobProvider from './jobProvider'

export default class extends JobProvider {
  constructor() {
    super({
      id: 'dmtk',
      name: 'domestika.org',
      logo: 'http://4.bp.blogspot.com/-_ntAal9lU2I/T3XBljnauCI/AAAAAAAAAWo/kS3eJcZZQvs/s490/domestika-logo.gif',
      scope: 'ul.jobs-list li.job-item',
      selectors: {
        title: 'h2.job-item__title a',
        url: 'h2.job-item__title a@href',
        date: 'div.job-item__date',
        company: 'h3.job-item__company',
        location: 'div.job-item__city',
        description: 'p.job-item__excerpt'
      }
    })
  }

  refine(item) {
    item.location = this.clean(item.location)
  }
}

Fix on scrap link for domestika provider


import {OS_DESKTOP} from './platform.shared'
import path from 'path'

export const isDev = process.env.NODE_ENV === 'development'
export const OS = OS_DESKTOP
export const isMobile = false

const runMode = process.env.KEYBASE_RUN_MODE || 'devel'
const envedPathOSX = {
  staging: 'KeybaseStaging',
  devel: 'KeybaseDevel',
  prod: 'Keybase'
}

function findSocketRoot () {
  const paths = {
    'darwin': `${process.env.HOME}/Library/Caches/${envedPathOSX[runMode]}/`,
    'linux': `${process.env.XDG_RUNTIME_DIR}/keybase.${runMode}/`
  }

  return paths[process.platform]
}

export const socketRoot = findSocketRoot()
export const socketName = 'keybased.sock'
export const socketPath = path.join(socketRoot, socketName)

function findDataRoot () {
  const paths = {
    'darwin': `${process.env.HOME}/Library/Application Support/${envedPathOSX[runMode]}/`,
    'linux': `${process.env.XDG_DATA_DIR}/keybase.${runMode}/`
  }

  return paths[process.platform]
}

export const dataRoot = findDataRoot()

import {OS_DESKTOP} from './platform.shared'
import path from 'path'

export const isDev = process.env.NODE_ENV === 'development'
export const OS = OS_DESKTOP
export const isMobile = false

const runMode = process.env.KEYBASE_RUN_MODE || 'devel'
const envedPathOSX = {
  staging: 'KeybaseStaging',
  devel: 'KeybaseDevel',
  prod: 'Keybase'
}

function findSocketRoot () {
  const paths = {
    'darwin': `${process.env.HOME}/Library/Caches/${envedPathOSX[runMode]}/`,
    'linux': `${process.env.XDG_RUNTIME_DIR}/keybase.${runMode}/`
  }

  if (runMode === 'prod') {
    paths['linux'] = `${process.env.XDG_RUNTIME_DIR}/keybase/`
  }

  return paths[process.platform]
}

export const socketRoot = findSocketRoot()
export const socketName = 'keybased.sock'
export const socketPath = path.join(socketRoot, socketName)

function findDataRoot () {
  const paths = {
    'darwin': `${process.env.HOME}/Library/Application Support/${envedPathOSX[runMode]}/`,
    'linux': `${process.env.XDG_DATA_DIR}/keybase.${runMode}/`
  }

  return paths[process.platform]
}

export const dataRoot = findDataRoot()

Support prod runmode on Linux


import Ember from 'ember';
import ApplicationRouteMixin from 'simple-auth/mixins/application-route-mixin';

export default Ember.Route.extend(ApplicationRouteMixin, {
  model() {
    const tournamentId = this.modelFor('tournament').get('id');

    return this.store.query('match', {tournamentId});
  },

  setupController(controller, model) {
    this._super(controller, model);

    const isDraft = this.modelFor('tournament').get('isDraft');
    controller.set('isDraft', isDraft);
  },

  actions: {
    goToSettings() {
      this.transitionTo('tournament.settings');
    }
  }

});

import Ember from 'ember';
import ApplicationRouteMixin from 'simple-auth/mixins/application-route-mixin';

const { Route, RSVP } = Ember;

export default Route.extend(ApplicationRouteMixin, {
  model() {
    const tournamentId = this.modelFor('tournament').get('id');

    let rsvpHash = {
      matches: this.get('store').query('match', {tournamentId}),
      teams: this.get('store').query('team', {tournamentId}),
    };

    return RSVP.hash(rsvpHash).then((hash) => {
      return hash.matches;
    });
  },

  setupController(controller, model) {
    this._super(controller, model);

    const isDraft = this.modelFor('tournament').get('isDraft');
    controller.set('isDraft', isDraft);
  },

  actions: {
    goToSettings() {
      this.transitionTo('tournament.settings');
    }
  }

});

Load teams on the first load of the tournament matches page


'use strict';

module.exports = DatasetView;

/** @ngInject **/
function DatasetView() {
  return {
    scope: {
      participant: '=',
      dataset: '=',
      onEdit: '&'
    },
    template: require('./datasetView.directive.html'),

    controllerAs: 'vm',
    bindToController: true,
    /** @ngInject **/
    controller: function($filter) {
      var self = this;

      self.getValue = getValue;

      function getValue(row, column){
        // if (column.LookupQuery && self.lookups[column.LookupQuery]) {
        //   var val = _.find(self.lookups[column.LookupQuery].rows, 'Key', row[column.Name]);
        //   return val === undefined ? '' : val.Label;
        // }else

        if (column.RangeURI === 'http://www.w3.org/2001/XMLSchema#dateTime'){
          return $filter('date')(row[column.Name], 'shortDate');
        }else{
          return row[column.Name];
        }
      }
    }
  };
}

'use strict';

module.exports = DatasetView;

/** @ngInject **/
function DatasetView() {
  return {
    scope: {
      participant: '=',
      dataset: '=',
      onEdit: '&'
    },
    template: require('./datasetView.directive.html'),

    controllerAs: 'vm',
    bindToController: true,
    /** @ngInject **/
    controller: function($filter, $scope, DatasetMetadataService) {
      var self = this;
      var _ = require('lodash');

      self.lookups = {};
      self.getValue = getValue;

      $scope.$watch(function () {
        return self.dataset;
      }, function (newVal) {
        if(newVal && self.dataset.columns){
          console.log("grabbing lookups");
          self.dataset.columns
            .filter(function(column) {
              return !!column.LookupQuery;
            })
            .forEach(function (column) {
              var lookupQuery = column.LookupQuery;
              DatasetMetadataService.getLookups(lookupQuery)
                .then((lookup) => self.lookups[lookupQuery] = lookup);
            });
        }
      });

      function getValue(row, column){
        if (column.LookupQuery && self.lookups[column.LookupQuery]) {
          var val = _.find(self.lookups[column.LookupQuery].rows, 'Key', row[column.Name]);
          return val === undefined ? '' : val.Label;
        }else if (column.RangeURI === 'http://www.w3.org/2001/XMLSchema#dateTime'){
          return $filter('date')(row[column.Name], 'shortDate');
        }else{
          return row[column.Name];
        }
      }
    }
  };
}

Fix labels using lookups (introduced in 0.0.4)


var _ = require('underscore');
var Model = require('../../core/model');

/**
 *  This model is used for getting the total amount of values
 *  from the category.
 *
 */

module.exports = Model.extend({
  defaults: {
    url: '',
    totalCount: 0,
    categoriesCount: 0
  },

  url: function () {
    var url = this.get('url');
    var queryOptions = [];
    if (this.get('apiKey')) {
      queryOptions.push('api_key=' + this.get('apiKey'));
    } else if (this.get('authToken')) {
      var authToken = this.get('authToken');
      if (authToken instanceof Array) {
        _.each(authToken, function (token) {
          queryOptions.push('auth_token[]=' + token);
        });
      } else {
        queryOptions.push('auth_token=' + authToken);
      }
    }
    url += '?' + queryOptions.join('&');
    return url;
  },

  initialize: function () {
    this.bind('change:url', function () {
      this.fetch();
    }, this);
  },

  setUrl: function (url) {
    this.set('url', url);
  },

  parse: function (d) {
    // Calculating the total amount of all categories with the sum of all
    // values from this model included the aggregated (Other)
    return {
      categoriesCount: d.categoriesCount,
      totalCount: _.reduce(
        _.pluck(d.categories, 'value'),
        function (memo, value) {
          return memo + value;
        },
        0
      )
    };
  }
});

var _ = require('underscore');
var Model = require('../../core/model');

/**
 *  This model is used for getting the total amount of values
 *  from the category.
 *
 */

module.exports = Model.extend({
  defaults: {
    url: '',
    totalCount: 0,
    categoriesCount: 0
  },

  url: function () {
    var url = this.get('url');
    var queryOptions = [];
    if (this.get('apiKey')) {
      url += '?api_key=' + this.get('apiKey');
    } else if (this.get('authToken')) {
      var authToken = this.get('authToken');
      if (authToken instanceof Array) {
        _.each(authToken, function (token) {
          queryOptions.push('auth_token[]=' + token);
        });
      } else {
        queryOptions.push('auth_token=' + authToken);
      }
      url += '?' + queryOptions.join('&');
    }
    return url;
  },

  initialize: function () {
    this.bind('change:url', function () {
      this.fetch();
    }, this);
  },

  setUrl: function (url) {
    this.set('url', url);
  },

  parse: function (d) {
    // Calculating the total amount of all categories with the sum of all
    // values from this model included the aggregated (Other)
    return {
      categoriesCount: d.categoriesCount,
      totalCount: _.reduce(
        _.pluck(d.categories, 'value'),
        function (memo, value) {
          return memo + value;
        },
        0
      )
    };
  }
});

Fix widget url generation when missing apikey and authtoken


/*
	Example usage:

	var A = Class(function() {

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

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

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

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

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

var create = require('./create')

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

/*
	Example usage:

	var A = Class(function() {

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

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

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

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

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

var copy = require('./copy')

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

Use copy instead of create for easier debugging


'use strict';

let Games = require('./games.js');
let uuid = require('node-uuid');

let games = new Games(uuid.v4);

exports.registerRoutes = app => {
  app.get('/api/stats', (request, response) => {
    response.send(games.getAllPlayerStats());
  });

  app.post('/api/player', (request, response) => {
    response.send(games.addPlayer(request.body.name));
  });

  app.post('/api/player/:playerId/new-game', (request, response) => {
    response.send(games.newGame(request.params.playerId));
  });

  app.post('/api/player/:playerId/guess', (request, response) => {
    response.send(games.guess(request.params.playerId, request.body.guess));
  });

  app.get('/api/player/:playerId/stats', (request, response) => {
    response.send(games.getPlayerStats(request.params.playerId));
  });
};

'use strict';

let Games = require('./games.js');
let uuid = require('node-uuid');

let games = new Games(uuid.v4);

exports.registerRoutes = app => {
  app.get('/api', (request, response) => {
    response.send({
      name: "REST Mastermind server",
      endpoints: [
        { endpoint: '/api/stats', method: 'GET', purpose: 'Get the stats for all current players.' },
        { endpoint: '/api/player', method: 'POST', body: { name: 'Player Name' }, purpose: 'Register a new player.' },
        { endpoint: '/api/player/{playerId}', method: 'GET', purpose: 'Get the stats for a specific player.' },
        { endpoint: '/api/player/{playerId}/new-game', method: 'POST', body: {}, purpose: 'Start a new game for the player.' },
        { endpoint: '/api/player/{playerId}/guess', method: 'POST', body: { guess: '123456' }, purpose: 'Make a guess in the current game.' }
      ]
    });
  });

  app.get('/api/stats', (request, response) => {
    response.send(games.getAllPlayerStats());
  });

  app.post('/api/player', (request, response) => {
    response.send(games.addPlayer(request.body.name));
  });

  app.get('/api/player/:playerId', (request, response) => {
    response.send(games.getPlayerStats(request.params.playerId));
  });

  app.post('/api/player/:playerId/new-game', (request, response) => {
    response.send(games.newGame(request.params.playerId));
  });

  app.post('/api/player/:playerId/guess', (request, response) => {
    response.send(games.guess(request.params.playerId, request.body.guess));
  });
};

Create base api endpoint and adjust player stats path


import union from 'lodash/array/union';
import without from 'lodash/array/without';

export default class EnterLeaveCounter {
  constructor() {
    this.entered = [];
  }

  enter(enteringNode) {
    this.entered = union(
      this.entered.filter(node =>
        document.body.contains(node) &&
        (!node.contains || node.contains(enteringNode))
      ),
      [enteringNode]
    );

    return this.entered.length === 1;
  }

  leave(leavingNode) {
    this.entered = without(
      this.entered.filter(node =>
        document.body.contains(node)
      ),
      leavingNode
    );

    return this.entered.length === 0;
  }

  reset() {
    this.entered = [];
  }
}

import union from 'lodash/array/union';
import without from 'lodash/array/without';

export default class EnterLeaveCounter {
  constructor() {
    this.entered = [];
  }

  enter(enteringNode) {
    this.entered = union(
      this.entered.filter(node =>
        document.documentElement.contains(node) &&
        (!node.contains || node.contains(enteringNode))
      ),
      [enteringNode]
    );

    return this.entered.length === 1;
  }

  leave(leavingNode) {
    this.entered = without(
      this.entered.filter(node =>
        document.documentElement.contains(node)
      ),
      leavingNode
    );

    return this.entered.length === 0;
  }

  reset() {
    this.entered = [];
  }
}

Fix an edge case when a file is dropped outside <body>


import logger from '../logger'

const openedModules = {}

const hotModules = {}

const createHotModule = () => ({ instances: [], updateTimeout: 0 })

export const hotModule = moduleId => {
  if (!hotModules[moduleId]) {
    hotModules[moduleId] = createHotModule()
  }
  return hotModules[moduleId]
}

export const isOpened = sourceModule =>
  sourceModule && !!openedModules[sourceModule.id]

export const enter = sourceModule => {
  if (sourceModule && sourceModule.id) {
    openedModules[sourceModule.id] = true
  } else {
    logger.warn(
      'React-hot-loader: no `module` variable found. Do you shadow system variable?',
    )
  }
}

export const leave = sourceModule => {
  if (sourceModule && sourceModule.id) {
    delete openedModules[sourceModule.id]
  }
}

import logger from '../logger'

const openedModules = {}

const hotModules = {}

const createHotModule = () => ({ instances: [], updateTimeout: 0 })

export const hotModule = moduleId => {
  if (!hotModules[moduleId]) {
    hotModules[moduleId] = createHotModule()
  }
  return hotModules[moduleId]
}

export const isOpened = sourceModule =>
  sourceModule && !!openedModules[sourceModule.id]

export const enter = sourceModule => {
  if (sourceModule && sourceModule.id) {
    openedModules[sourceModule.id] = true
  } else {
    logger.warn(
      'React-hot-loader: no `module` variable found. Did you shadow a system variable?',
    )
  }
}

export const leave = sourceModule => {
  if (sourceModule && sourceModule.id) {
    delete openedModules[sourceModule.id]
  }
}

Fix grammar mistake in commment


const createTransform = require('./transform')
const assert = require('assert')

let entityId = 0

function Entity (components, tags, renderer) {
  assert(!tags || Array.isArray(tags), 'Entity tags must be an array or null')
  this.id = entityId++
  this.tags = tags || []
  this.renderer = renderer

  this.components = components ? components.slice(0) : []

  this.transform = this.getComponent('Transform')
  if (!this.transform) {
    this.transform = createTransform({
      parent: null
    })
    this.components.unshift(this.transform)
  }

  this.components.forEach((component) => component.init(this))
}

Entity.prototype.dispose = function () {
  this.components.forEach((component) => {
    if (component.dispose) {
      component.dispose()
    }
  })
  // detach from the hierarchy
  this.transform.set({ parent: null })
}

Entity.prototype.addComponent = function (component) {
  this.components.push(component)
  component.init(this)
}

Entity.prototype.getComponent = function (type) {
  return this.components.find((component) => component.type === type)
}

module.exports = function createEntity (components, parent, tags) {
  return new Entity(components, parent, tags)
}

const createTransform = require('./transform')
const assert = require('assert')

let entityId = 0

function Entity (components, tags, renderer) {
  assert(!tags || Array.isArray(tags), 'Entity tags must be an array or null')
  this.id = entityId++
  this.tags = tags || []
  this.renderer = renderer

  this.components = components ? components.slice(0) : []

  this.componentsMap = new Map()
  this.components.forEach((component) => {
    this.componentsMap.set(component.type, component)
  })

  this.transform = this.getComponent('Transform')
  if (!this.transform) {
    this.transform = createTransform({
      parent: null
    })
    this.components.unshift(this.transform)
  }

  this.components.forEach((component) => component.init(this))
}

Entity.prototype.dispose = function () {
  this.components.forEach((component) => {
    if (component.dispose) {
      component.dispose()
    }
  })
  // detach from the hierarchy
  this.transform.set({ parent: null })
}

Entity.prototype.addComponent = function (component) {
  this.components.push(component)
  this.componentsMap.set(component.type, component)
  component.init(this)
}

// Only the last added component of that type will be returned
Entity.prototype.getComponent = function (type) {
  return this.componentsMap.get(type)
}

module.exports = function createEntity (components, parent, tags) {
  return new Entity(components, parent, tags)
}

Add hashmap for fast components lookups


describe('Processes', function() {
    'use strict';
    let atf = require('../../specs/atf');
    let ropts = {
        db: 'mctest',
        port: 30815
    };

    let r = require('rethinkdbdash')(ropts);
    let p = require('./processes')(r);

    describe('#create', function() {
        it('should do something', function(done) {
            function validate(err) {
                console.log("err", err);
                done(err);
            }
            atf(function *() {
                yield p.create({});
            }, validate);
        });
    });
});

describe('Processes', function() {
    'use strict';
    let atf = require('../../specs/atf');
    let ropts = {
        db: 'mctest',
        port: 30815
    };

    let r = require('rethinkdbdash')(ropts);
    let p = require('./processes')(r);

    describe('#create', function() {
        it('should create a process', function(done) {
            function validate(err) {
                console.log("err", err);
                done(err);
            }
            atf(function *() {
                let process = {
                    name: 'as_received',
                    owner: 'test@mc.org',
                    template_id: 'as_received',
                    description : '',
                    project_id: 'abc123',
                    settings: [],
                    measurements: []
                };
                yield p.create(process);
            }, validate);
        });
    });
});

Set up a valid process to begin testing against.


/*jshint node:true*/
module.exports = {
  description: 'ember-cli-tooltipster',
  normalizeEntityName: function() {
    // this prevents an error when the entityName is not specified
  },

  afterInstall: function( /*options*/ ) {
    return this.addPackageToProject([{
      name: 'tooltipster',
      target: '4.2.2'
    }]);
  }
};

/*jshint node:true*/
module.exports = {
  description: 'ember-cli-tooltipster',
  normalizeEntityName: function() {
    // this prevents an error when the entityName is not specified
  },

  afterInstall: function( /*options*/ ) {
    return this.addPackagesToProject([{
      name: 'tooltipster',
      target: '4.2.2'
    }]);
  }
};

Fix addPackagesToProject in blueprint afterInstall


// Copyright (c) Martin Costello, 2017. All rights reserved.
// Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information.

var AlexaAppServer = require("alexa-app-server");
var env = require("node-env-file");

env(__dirname + "/.env");

console.log("TfL App Id :", process.env.TFL_APP_ID);
console.log("TfL App Key:", process.env.TFL_APP_KEY);

AlexaAppServer.start({
  server_root: __dirname,
  public_html: "static",
  app_dir: "./..",
  app_root: "/",
  port: 3001,
  preRequest: function (json, request, response) {
  },
  postRequest: function (json, request, response) {
  }
});

// Copyright (c) Martin Costello, 2017. All rights reserved.
// Licensed under the Apache 2.0 license. See the LICENSE file in the project root for full license information.

var AlexaAppServer = require("alexa-app-server");
var env = require("node-env-file");
var path = require("path");

env(path.join(__dirname, ".env"));

console.log("TfL App Id :", process.env.TFL_APP_ID);
console.log("TfL App Key:", process.env.TFL_APP_KEY);

AlexaAppServer.start({
  server_root: __dirname,
  public_html: "static",
  app_dir: "./..",
  app_root: "/",
  port: 3001,
  preRequest: function (json, request, response) {
  },
  postRequest: function (json, request, response) {
  }
});

Use path instead of concatenation


"use strict"

import Context from "./context"
import ShadowTree from "./shadowtree"

class Lint {
    constructor(tree, filename = null, namespace = []) {
        Object.assign(
            this,
            {
                filename: filename,
                namespace: namespace,
                tree: tree,
            }
        );
    }
    check() {
        return ShadowTree.Node.typed(this.tree).check(new Context());
    }
    static check(tree, filename = null) {
        var l = new Lint(tree, filename);
        return l.check();
    }
};

import PHPStrictError from "./phpstricterror"
Lint.PHPStrictError = PHPStrictError
Lint.ShadowTree = ShadowTree
module.exports = Lint;

"use strict"

import Context from "./context"
import ShadowTree from "./shadowtree"
import PHPStrictError from "./phpstricterror"

class Lint {
    static get PHPStrictError() {
        return PHPStrictError
    }
    static get ShadowTree() {
        return ShadowTree
    }
    constructor(tree, filename = null, namespace = []) {
        Object.assign(
            this,
            {
                filename: filename,
                namespace: namespace,
                tree: tree,
            }
        );
    }
    check() {
        return ShadowTree.Node.typed(this.tree).check(new Context());
    }
    static check(tree, filename = null) {
        var l = new Lint(tree, filename);
        return l.check();
    }
};

module.exports = Lint;

Use static properties for the sub-items


import React from 'react';
import axios from 'axios';

class App extends React.Component {

  render() {
    return (
      <Abc/>
    )
  }
}

class Abc extends React.Component {
  render() {
    return (
      <div>
        <button onClick={this.getList}>get List</button>
      </div>
    )
  }
  getList() {
    axios.get('/api/get/xss.com')
      .then( response => { console.dir(response); alert(response); } ) // SUCCESS
      .catch( response => { console.dir(response); } ); // ERROR
  }
}

export default App;

import React from 'react';
import axios from 'axios';

class App extends React.Component {

  render() {
    return (
      <SiteList/>
    )
  }
}

class SiteInfo extends React.Component {
    render() {
        return(

{this.props.rId} - {this.props.url}, {this.props.count}, {this.props.creation}, {this.props.latest}

        );
    }
}

class SiteList extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      url: "default",
      responseData: [],
    };
    this.getList = this.getList.bind(this);
    this.handleUrl = this.handleUrl.bind(this);
    this.keyDownCheck = this.keyDownCheck.bind(this);
  }
  handleUrl(event) {
    this.setState({
      url: event.target.value
    });
  }

  render() {
    return (

        <input placeholder="press enter" type="text" onChange={this.handleUrl} onKeyDown={this.keyDownCheck}></input>
        <button onClick={this.getList}>GET LIST !</button>

{this.state.url}

        {this.state.responseData.map((r, i) => {
          return (
            <SiteInfo rId={r.rId}
              url={r.url}
              count={r.count}
              creation={r.creation}
              latest={r.latest}
              key={i}
            />
          );
        })}

    )
  }
  keyDownCheck(event) {
    if (event.keyCode == 13) {
      this.getList();
    }
  }
  getList() {
    axios.get('/api/get/xss.com')
      .then( response => {
        this.setState({
            responseData: response.data
      })})
      .catch( response => { console.dir(response); } );
  }
}

export default App;

Add get list ui and feature