/**
 * User model
 */
import Joi from 'joi'
import * as utils from './utils'

export const INDEXES = []
export const TABLE = 'users'
export const TYPE = 'User'

export const UserSchema = Joi.object().keys({
  createdAt: Joi.date(),
  id: Joi.string().guid(),
  name: Joi.string().max(256).default('').allow(''),
  email: Joi.string().email().default('').allow('')
})

export const validate = utils.createValidate(UserSchema)

export const get = utils.createGet(TABLE)

export async function create (r, values) {
  const userValues = validate(values)

  const { generated_keys: [userId] } = await r.table(TABLE).insert({
    createdAt: r.now(),
    ...userValues
  })
  return userId
}

/**
 * User model
 */
import Joi from 'joi'
import BaseModel from './model'

const UserSchema = Joi.object()
.keys({
  createdAt: Joi.date(),
  id: Joi.string().guid(),
  name: Joi.string().max(256).default('').allow(''),
  email: Joi.string().email().default('').allow('')
})

const PROPS = {
  SCHEMA: UserSchema,
  INDEXES: [],
  TABLE: 'users',
  TYPE: 'User'
}

export default class User extends BaseModel {
}
Object.assign(User.prototype, PROPS)

Update User to use BaseModel


export function rowsValuesToString(rows) {
  return rows.map(rowValuesToString);
}

export function rowValuesToString(row) {
  if (Array.isArray(row)) {
    return rowsValuesToString(row);
  }

  return Object.keys(row).reduce((_row, col) => {
    _row[col] = valueToString(row[col]);
    return _row;
  }, {});
}

export function valueToString(value) {
  if (typeof value === 'boolean') {
    return value.toString();
  }
  if (!value) {
    return value;
  }
  if (value.toISOString) {
    return value.toISOString();
  }
  if (typeof value === 'object') {
    return JSON.stringify(value);
  }
  return value;
}

export function rowsValuesToString(rows) {
  return rows.map(rowValuesToString);
}

export function rowValuesToString(row) {
  if (Array.isArray(row)) {
    return rowsValuesToString(row);
  }

  return Object.keys(row).reduce((_row, col) => {
    _row[col] = valueToString(row[col]);
    return _row;
  }, {});
}

export function valueToString(value) {
  if (typeof value === 'boolean') {
    return value.toString();
  }
  if (!value) {
    return String(value);
  }
  if (value.toISOString) {
    return value.toISOString();
  }
  if (typeof value === 'object') {
    return JSON.stringify(value);
  }
  return String(value);
}

Fix problem not rendering null values


var QuestAnswerView = Backbone.View.extend({
  el: "#view",

  tagName: "div",

  events: {
    "click .btn.submit-answer":   "save"
  },

  initialize: function() {
    //this.listenTo(this.model, "change", this.render);
    this._modelBinder = new Backbone.ModelBinder();
  },

  render: function() {
    this.$el.html(AnswerTpl.render({answer: this.model.attributes}));
    this._modelBinder.bind(this.model, this.el);
    console.log('Answer Rendered');
    return this;
  },

  save: function(){
    return this.model.save('questionID','value', {
      success: function(){ alert('Answer Submitted!'); },
      error: function(){ alert('Error while saving Answer'); }
    });
  }
});

var QuestAnswerView = Backbone.View.extend({
  el: "#view",

  tagName: "div",

  events: {
    "click .btn.submit-answer":   "save"
  },

  initialize: function() {
    //this.listenTo(this.model, "change", this.render);
    this._modelBinder = new Backbone.ModelBinder();
  },

  render: function() {
    this.$el.html(AnswerTpl.render({answer: this.model.attributes}));
    this._modelBinder.bind(this.model, this.el);
    console.log('Answer Rendered');
    return this;
  },

  save: function(){
    return this.model.save([], {
      success: function(){ alert('Answer Submitted!'); },
      error: function(){ alert('Error while saving Answer'); }
    });
  }
});

Fix a bug in submitting an answer


RocketChat.Migrations.add({
	version: 94,
	up() {
		const query = {
			'emails.address.address': { $exists: true }
		};

		RocketChat.models.Users.find(query, {'emails.address.address': 1}).forEach((user) => {
			let emailAddress;
			user.emails.some(email => {
				if (email.address && email.address.address) {
					emailAddress = email.address.address;
					return true;
				}
			});
			RocketChat.models.Users.update({
				_id: user._id,
				'emails.address.address': emailAddress
			}, {
				$set: {
					'emails.$.address': emailAddress
				}
			});
		});
	}
});

RocketChat.Migrations.add({
	version: 94,
	up() {
		const query = {
			'emails.address.address': { $exists: true }
		};

		RocketChat.models.Users.find(query, {'emails.address.address': 1}).forEach((user) => {
			let emailAddress;
			user.emails.some(email => {
				if (email.address && email.address.address) {
					emailAddress = email.address.address;
					return true;
				}
			});
			const existingUser = RocketChat.models.Users.findOne({ 'emails.address': emailAddress }, { fields: { _id: 1 } });
			if (existingUser) {
				RocketChat.models.Users.update({
					_id: user._id,
					'emails.address.address': emailAddress
				}, {
					$unset: {
						'emails.$': 1
					}
				});
			} else {
				RocketChat.models.Users.update({
					_id: user._id,
					'emails.address.address': emailAddress
				}, {
					$set: {
						'emails.$.address': emailAddress
					}
				});
			}
		});
	}
});

Fix migration if email already exists


import * as constants from '../../constants'

export function documentCapture(payload) {
  return {
    type: constants.DOCUMENT_CAPTURE,
    payload
  }
}

export function captureIsValid(payload) {
  return {
    type: constants.CAPTURE_IS_VALID,
    payload
  }
}

export function clearDocuments(payload) {
  return {
    type: constants.CLEAR_DOCUMENTS,
    payload
  }
}

export function faceCapture(payload) {
  return {
    type: constants.FACE_CAPTURE,
    payload
  }
}

export function clearFaces(payload) {
  return {
    type: constants.CLEAR_FACES,
    payload
  }
}

import * as constants from '../../constants'

export function createCapture(payload) {
  return {
    type: constants.CAPTURE_CREATE,
    payload
  }
}

export function validCapture(payload) {
  return {
    type: constants.CAPTURE_VALID,
    payload
  }
}

export function deleteCaptures(payload) {
  return {
    type: constants.CAPTURE_DELETE,
    payload
  }
}

Clean up capture action creators


mi2JS.comp.add('base/Button', 'Base', '',

// component initializer function that defines constructor and adds methods to the prototype
function(proto, superProto, comp, superComp){

	proto.construct = function(el, tpl, parent){
		superProto.construct.call(this, el, tpl, parent);

		this.action = this.attr("action") || "action";
		this.event  = this.attr("event")  || "action";
		this.lastClick = 0;
		this.listen(el,"click",function(evt){
			evt.stop();
		});

		this.listen(el,"mousedown",function(evt){
			if(evt.which != 1) return; // only left click
			evt.stop();
			if(this.isEnabled() && this.parent.fireEvent){
				var now = new Date().getTime();
				if(now -this.lastClick > 300){ // one click per second
					this.parent.fireEvent(this.event, {
						action: this.action,
						button:this,
						domEvent: evt,
						src:this,
						eventFor: 'parent'
					});
					this.lastClick = now;
				}
			}
		});

	};

	proto.setValue = function(value){
		this.el.value = value;
	};

	proto.getValue = function(value){
		return this.el.value;
	};

});

mi2JS.comp.add('base/Button', 'Base', '',

// component initializer function that defines constructor and adds methods to the prototype
function(proto, superProto, comp, superComp){

	proto.construct = function(el, tpl, parent){
		superProto.construct.call(this, el, tpl, parent);

		this.lastClick = 0;
		this.listen(el,"click",function(evt){
			evt.stop();
		});

		this.listen(el,"mousedown",function(evt){
			if(evt.which != 1) return; // only left click
			evt.stop();
			if(this.isEnabled() && this.parent.fireEvent){
				var now = new Date().getTime();
				if(now -this.lastClick > 300){ // one click per second
					this.parent.fireEvent(this.getEvent(), {
						action: this.getAction(),
						button:this,
						domEvent: evt,
						src:this,
						eventFor: 'parent'
					});
					this.lastClick = now;
				}
			}
		});

	};

	proto.getEvent = function(){
		return this.attr("event") || "action";
	};

	proto.getAction = function(){
		return this.attr("action") || "action";
	};

	proto.setValue = function(value){
		this.el.value = value;
	};

	proto.getValue = function(value){
		return this.el.value;
	};

});

Allow subclass customizing event and action


"use strict";

var Router = require("i40");

function Routes() {
    this._router = Router();
}

Routes.prototype._router = null;

Routes.prototype.add = function (route, fn) {
    if (arguments.length < 2) {
        fn = arguments[0];
        route = "*";
    }
    this._router.addRoute.call(this._router, route, fn);
    return this;
};

Routes.prototype.get = addByMethod("GET");
Routes.prototype.post = addByMethod("POST");
Routes.prototype.put = addByMethod("PUT");
Routes.prototype.delete = addByMethod("DELETE");

Routes.prototype.match = function (url) {
    return this._router.match(url);
};

function addByMethod(method) {
    return function (fn) {
        return this.add(function checkMethod(req, res, next) {
            if (req.method === method) {
                fn.call(this, req, res, next);
            }
        });
    };
}

module.exports = Routes;

"use strict";

var Router = require("i40");

var slice = Array.prototype.slice;

function Routes() {
    this._router = new Router();
}

Routes.prototype._router = null;

Routes.prototype.add = function (route, fn1, fn2, fn3) {
    var args = normalizeArguments(arguments);

    args.fns.forEach(function (fn) {
         this._router.addRoute(args.route, fn);
    }, this);

    return this;
};

Routes.prototype.get = addByMethod("GET");
Routes.prototype.post = addByMethod("POST");
Routes.prototype.put = addByMethod("PUT");
Routes.prototype.delete = addByMethod("DELETE");

Routes.prototype.match = function (url) {
    return this._router.match(url);
};

function addByMethod(method) {
    return function (route, fn) {
        var args = normalizeArguments(arguments);

        args.fns = args.fns.map(function (fn) {
            return function checkMethod(req, res, next) {
                if (req.method === method) {
                    fn.call(this, req, res, next);
                }
            };
        });

        return this.add.apply(this, [].concat(args.route, args.fns));
    };
}

function normalizeArguments(args) {
    var route = args[0];
    var fns;
    var i = 0;

    if (typeof route === "string") {
        i = 1;
    } else {
        route = "*";
    }
    fns = slice.call(args, i);

    return {
        route: route,
        fns: fns
    };
}

module.exports = Routes;

Fix bug where not all listeners have been passed to the router


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

foam.CLASS({
  package: 'com.chrome.origintrials.model',
  name: 'Token',
  properties: [
    {
      class: 'String',
      name: 'origin'
    },
    {
      class: 'String',
      name: 'feature'
    },
    {
      class: 'String',
      name: 'emailAddress'
    },
    {
      class: 'String',
      name: 'name'
    },
    {
      class: 'String',
      name: 'rowNumber'
    },
    {
      class: 'String',
      name: 'token'
    },
    {
      class: 'DateTime',
      name: 'expryTime'
    },
    {
      class: 'String',
      name: 'id',
    },
    {
      class: 'Boolean',
      name: 'isSubdomain'
    }
  ]
});

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

foam.CLASS({
  package: 'com.chrome.origintrials.model',
  name: 'Token',
  properties: [
    {
      class: 'String',
      name: 'origin'
    },
    {
      class: 'String',
      name: 'feature'
    },
    {
      class: 'String',
      name: 'emailAddress'
    },
    {
      class: 'String',
      name: 'name'
    },
    {
      class: 'String',
      name: 'rowNumber'
    },
    {
      class: 'String',
      name: 'token'
    },
    {
      class: 'DateTime',
      name: 'expiryTime'
    },
    {
      class: 'String',
      name: 'id',
    },
    {
      class: 'Boolean',
      name: 'isSubdomain'
    }
  ]
});

Fix typo in expirtyTime property name.


AV.VisualizationView = Backbone.View.extend({
    el: '#visualization',
    // The rendering of the visualization will be slightly
    // different here, because there is no templating necessary:
    // The server gives back a page.
    render: function() {
        this.model.url = this.model.urlRoot + this.model.id +
            '/view?mode=heatmap&condensed=true';
        var response = $.ajax({
            url: this.model.url,
            type: "GET"
        }).done(_.bind(function(d) {
            console.log(d[0]);
            //If the server returns an HTML document
            if (d[0] != 'R') {
                return d;
            } else { //Rendering
                console.log("Yo dawg, I heard you like recursion, so I put" +
                            " recursion in your recursion so you can recur" +
                            " while you recur");
                setTimeout(function(){}, 1000);
                return this.render();
            }
        }, this));

        this.$el.attr('src', this.model.url).load(_.bind(function() {
            var iframe = this.$el.contents();
            iframe.find('.menubar').remove();
			iframe.find('.title-bar').remove();
        }, this));

        $('#basicModal').modal({
            show: true
        });
    }
});

AV.VisualizationView = Backbone.View.extend({
    el: '#visualization',
    // The rendering of the visualization will be slightly
    // different here, because there is no templating necessary:
    // The server gives back a page.
    render: function() {
        this.model.url = this.model.urlRoot + this.model.id +
            '/view?mode=heatmap&condensed=true';
        var response = $.ajax({
            url: this.model.url,
            type: "GET"
        }).done(_.bind(function(d) {
            //If the server returns an HTML document
            if (d[0] != 'R') {
                return d;
            } else { //Rendering
                setTimeout(function(){}, 1000);
                return this.render();
            }
        }, this));

        this.$el.attr('src', this.model.url).load(_.bind(function() {
            var iframe = this.$el.contents();
            // iframe.find('.menubar').remove();
			// iframe.find('.title-bar').remove();
        }, this));

        $('#basicModal').modal({
            show: true
        });
    }
});

Comment out @bubil 's menu-bar removal


import React from 'react';

import LanguageLink from '../../components/LanguageLink/LanguageLink';
import guideListConfig from '../guideList/config';

import './GuidesMenu.scss';

const GuidesMenu = () => (

Back To Overview

      <input type="radio" name="guide" id="placeholder-radio-button" />
      {guideListConfig.sections.map(section => (

{section.name}

          {section.guides.map((guide, index) => (

              <input type="radio" name="guide" id={`${section.name}${index}`} />
              <label htmlFor={`${section.name}${index}`}>

{guide.title}

                {guide.languages.map(language => (
                  <LanguageLink
                    key={language}
                    language={language}
                    url={`${guide.baseUrl}${language}/`}
                  />
                ))}

          ))}

      ))}

);

export default GuidesMenu;

import React from 'react';
import { Link } from 'react-router';

import LanguageLink from '../../components/LanguageLink/LanguageLink';
import guideListConfig from '../guideList/config';

import './GuidesMenu.scss';

const GuidesMenu = () => (

      <Link to="/guides/">

Back To Overview

      </Link>
      <input type="radio" name="guide" id="placeholder-radio-button" />
      {guideListConfig.sections.map(section => (

{section.name}

          {section.guides.map((guide, index) => (

              <input type="radio" name="guide" id={`${section.name}${index}`} />
              <label htmlFor={`${section.name}${index}`}>

{guide.title}

                {guide.languages.map(language => (
                  <LanguageLink
                    key={language}
                    language={language}
                    url={`${guide.baseUrl}${language}/`}
                  />
                ))}

          ))}

      ))}

);

export default GuidesMenu;

Add link for Back to Overview in guides menu


/* @flow */

import {getExternalIP} from './external-ip'

const BASE = 'xip.io'

function isValidIpv4Addr(ip) {
  return /^(?=\d+\.\d+\.\d+\.\d+$)(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\.?){4}$/.test(ip)
}

export function getXIPSubdomain() {
  const externalIP = getExternalIP()

  if (externalIP === '127.0.0.1') {
    // shorten
    return `0.${BASE}`
  }

  if (isValidIpv4Addr(externalIP)) {
    // invalid IP address, fallback to local
    return `0.${BASE}`
  }

  return `${externalIP}.${BASE}`
}

export function getHostForService(service: string, navyNormalisedName: string) {
  return `${service}.${navyNormalisedName}.${process.env.NAVY_EXTERNAL_SUBDOMAIN || getXIPSubdomain()}`
}

export function getUrlForService(service: string, navyNormalisedName: string) {
  return `http://${getHostForService(service, navyNormalisedName)}`
}

/* @flow */

import {getExternalIP} from './external-ip'

const BASE = 'xip.io'

function isValidIpv4Addr(ip) {
  return /^([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\.([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\.([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\\.([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])$/g.test(ip)
}

export function getXIPSubdomain() {
  const externalIP = getExternalIP()

  if (externalIP === '127.0.0.1') {
    // shorten
    return `0.${BASE}`
  }

  if (isValidIpv4Addr(externalIP)) {
    // invalid IP address, fallback to local
    return `0.${BASE}`
  }

  return `${externalIP}.${BASE}`
}

export function getHostForService(service: string, navyNormalisedName: string) {
  return `${service}.${navyNormalisedName}.${process.env.NAVY_EXTERNAL_SUBDOMAIN || getXIPSubdomain()}`
}

export function getUrlForService(service: string, navyNormalisedName: string) {
  return `http://${getHostForService(service, navyNormalisedName)}`
}

Fix NAVY_EXTERNAL_IP and NAVY_HOST not working


/**
 * The loads happen much quicker than Nightwatch can pull, so we're testing the aftermath of the successive loads
 */
module.exports = {

	'assets should not be rendered': function (browser) { browser
		.url('http://localhost:8080/visible/')
		.waitForElementVisible('#app', 1000)

		.assert.elementNotPresent('.vv-image')
		.assert.elementNotPresent('.vv-video')
	},

	'image should render when general offset reached': function (browser) { browser
		.execute('scrollTo(0, 1)')

		.assert.elementPresent('.vv-image')
		.assert.elementNotPresent('.vv-video')
	},

	'video should render when offset override reached': function (browser) { browser
		.execute('scrollTo(0, 200 + 1)')

		.assert.elementPresent('.vv-image')
		.assert.elementPresent('.vv-video')
	},

	'video should stop playing when scrolling back up': function (browser) { browser

		// Wait for video to start playing
		.waitForElementPresent('.vv-visual.vv-playing', 1000)

		.execute('scrollTo(0, 0)')
		.assert.cssClassNotPresent('.vv-visual', '.vv-playing')

		.end()
	},

}

/**
 * The loads happen much quicker than Nightwatch can pull, so we're testing the aftermath of the successive loads
 */
module.exports = {

	'assets should not be rendered': function (browser) { browser
		.url('http://localhost:8080/visible/')
		.waitForElementVisible('#app', 1000)

		.assert.elementNotPresent('.vv-image')
		.assert.elementNotPresent('.vv-video')
	},

	'image should render when general offset reached': function (browser) { browser
		.execute('scrollTo(0, 1)')

		.waitForElementPresent('.vv-image', 500)
		.assert.elementNotPresent('.vv-video')
	},

	'video should render when offset override reached': function (browser) { browser
		.execute('scrollTo(0, 200 + 1)')

		.waitForElementPresent('.vv-image', 500)
		.waitForElementPresent('.vv-video', 500)
	},

	'video should stop playing when scrolling back up': function (browser) { browser

		// Wait for video to start playing
		.waitForElementPresent('.vv-visual.vv-playing', 1000)

		.execute('scrollTo(0, 0)')
		.assert.cssClassNotPresent('.vv-visual', '.vv-playing')

		.end()
	},

}

Allow elements to take a bit before entering dom


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

import {getPackageDir} from './paths'

export function exitOnPackageNotFound() {
  if (getPackageDir())
    return
  process.stdout.write('No valid “package.json” found.')
  process.exit(1)
}

export function pickNonFalsy(obj:Object):Object {
  let result = {}
  for (let prop in obj) {
    if (obj[prop])
      result[prop] = obj[prop]
  }
  return result
}

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

import {getPackageDir} from './paths'
import {join} from 'path'

export function exitOnPackageNotFound() {
  if (getPackageDir())
    return
  process.stdout.write('No valid “package.json” found.')
  process.exit(1)
}

export function getProjectName() {
  const PACKAGE_JSON = join(getPackageDir(), 'package.json')
  return require(PACKAGE_JSON).name
}

export function pickNonFalsy(obj:Object):Object {
  let result = {}
  for (let prop in obj) {
    if (obj[prop])
      result[prop] = obj[prop]
  }
  return result
}

Add helper to get project name


'use strict';

var Node = require('../node');
var debug = require('../../util/debug')('analysis:line-to-single-point');

var TYPE = 'line-to-single-point';
var PARAMS = {
    source: Node.PARAM.NODE(Node.GEOMETRY.POINT),
    destination_longitude: Node.PARAM.NUMBER(),
    destination_latitude: Node.PARAM.NUMBER(),
};

var LineToSinglePoint = Node.create(TYPE, PARAMS);

module.exports = LineToSinglePoint;
module.exports.TYPE = TYPE;
module.exports.PARAMS = PARAMS;

LineToSinglePoint.prototype.sql = function() {
    var sql = lineToSinglePointQueryTemplate({
        source: this.source.getQuery(),
        columns: this.source.getColumns(true).join(', '),
        destination_longitude: this.destination_longitude,
        destination_latitude: this.destination_latitude
    });

    debug(sql);

    return sql;
};

var lineToSinglePointQueryTemplate = Node.template([
    'SELECT',
    '  ST_MakeLine(',
    '    the_geom,',
    '    ST_SetSRID(',
    '      ST_MakePoint(',
    '        {{=it.destination_longitude}},',
    '        {{=it.destination_latitude}}',
    '      ),',
    '      4326',
    '    )',
    '  ) AS the_geom,',
    '  {{=it.columns}}',
    'FROM ({{=it.source}}) _cdb_analysis_source_points',
].join('\n'));

'use strict';

var Node = require('../node');
var debug = require('../../util/debug')('analysis:line-to-single-point');

var TYPE = 'line-to-single-point';
var PARAMS = {
    source: Node.PARAM.NODE(Node.GEOMETRY.POINT),
    destination_longitude: Node.PARAM.NUMBER(),
    destination_latitude: Node.PARAM.NUMBER(),
};

var LineToSinglePoint = Node.create(TYPE, PARAMS);

module.exports = LineToSinglePoint;
module.exports.TYPE = TYPE;
module.exports.PARAMS = PARAMS;

LineToSinglePoint.prototype.sql = function() {
    var skipTheGeoms = true;
    var sql = lineToSinglePointQueryTemplate({
        source: this.source.getQuery(),
        columns: this.source.getColumns(skipTheGeoms).join(', '),
        destination_longitude: this.destination_longitude,
        destination_latitude: this.destination_latitude
    });

    debug(sql);

    return sql;
};

var lineToSinglePointQueryTemplate = Node.template([
    'SELECT',
    '  ST_MakeLine(',
    '    the_geom,',
    '    ST_SetSRID(',
    '      ST_MakePoint(',
    '        {{=it.destination_longitude}},',
    '        {{=it.destination_latitude}}',
    '      ),',
    '      4326',
    '    )',
    '  ) AS the_geom,',
    '  {{=it.columns}}',
    'FROM ({{=it.source}}) _cdb_analysis_source_points',
].join('\n'));

Use a name param instead of a boolean value


'use strict';

var markovWordsetBuilder = (function() {

	var max_words = 80000;

	function stripChars(word) {
		return word.replace(/[^\w\s\.\!\?\'\,\—\-]/gi, '');
	}

	function addWords(words, delimiter) {
		var wordSet = [];

		var aw = words.split(delimiter);
		var len = aw.length;
		if (len > max_words) len = max_words;
		console.log("adding words (max of " + len + ")");

		for (var i = 0; i < len; i++) {
			var word = stripChars(aw[i]);
			if (word.length > 0) wordSet.push(word);
		}
		return wordSet;
	}

	return { addWords : addWords }

})();

'use strict';

var markovWordsetBuilder = (function() {

	var max_words = 80000;

	function stripChars(word) {
		return word.replace(/[^A-Za-z0-9\s\.\!\?\'\,\—\-]/gi, '');
	}

	function addWords(words, delimiter) {
		var wordSet = [];

		var aw = words.split(delimiter);
		var len = aw.length;
		if (len > max_words) len = max_words;
		console.log("adding words (max of " + len + ")");

		for (var i = 0; i < len; i++) {
			var word = stripChars(aw[i]);
			if (word.length > 0) wordSet.push(word);
		}
		return wordSet;
	}

	return { addWords : addWords }

})();

Remove underscores from words when building wordSet


import mapService from 'new-dashboard/core/map-service';
import { visualizations as fakeVisualizations } from '../fixtures/visualizations';
jest.mock('carto-node');

describe('mapService', () => {
  describe('.fetchMaps', () => {
    describe('when no parameters are given', () => {
      let response;
      beforeAll(async () =>  {
        response = await mapService.fetchMaps();
      })
      it('should return a list of visualizations filtered and ordered by default', async () => {
        expect(response.visualizations).toEqual(fakeVisualizations);
      });
      it('should return metadata values', async () => {
        expect(response.total_entries).toEqual(1);
        expect(response.total_likes).toEqual(1);
        expect(response.total_shared).toEqual(32);
        expect(response.total_user_entries).toEqual(6);
      });
    })
  });
});

import mapService from 'new-dashboard/core/map-service';
import { visualizations as fakeVisualizations } from '../fixtures/visualizations';
jest.mock('carto-node');

describe('mapService', () => {
  describe('.fetchMaps', () => {
    describe('when no parameters are given', () => {
      let response;
      beforeAll(done =>  {
        mapService.fetchMaps().then(data => {
          response = data;
          done();
        })
      })
      it('should return a list of visualizations filtered and ordered by default', async () => {
        expect(response.visualizations).toEqual(fakeVisualizations);
      });
      it('should return metadata values', async () => {
        expect(response.total_entries).toEqual(1);
        expect(response.total_likes).toEqual(1);
        expect(response.total_shared).toEqual(32);
        expect(response.total_user_entries).toEqual(6);
      });
    })
  });
});

Use promise instead async fn


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

export default class FormioProvider extends Component {
  static PropTypes = {
    formio: PropTypes.object.isRequired,
    children: PropTypes.element.isRequired
  };

  static childContextTypes = {
    formio: PropTypes.object.isRequired
  };

  static displayName = 'Provider';

  getChildContext() {
    return {formio: this.formio};
  }

  constructor(props, context) {
    super(props, context);
    this.formio = props.formio;
  }

  render() {
    return Children.only(this.props.children);
  }
}

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

export default class FormioProvider extends Component {
  static propTypes = {
    formio: PropTypes.object.isRequired,
    children: PropTypes.element.isRequired
  };

  static childContextTypes = {
    formio: PropTypes.object.isRequired
  };

  static displayName = 'Provider';

  getChildContext() {
    return {formio: this.formio};
  }

  constructor(props, context) {
    super(props, context);
    this.formio = props.formio;
  }

  render() {
    return Children.only(this.props.children);
  }
}

Fix proptypes property of FormProvider


const webpack = require("webpack");
const webpackDevServer = require('webpack-dev-server');
const path = require('path');
const baseConfig = require('../config/webpack.config.dist');

const port = 8080;
const serverURI = `webpack-dev-server/client?http://localhost:${port}/`;

let browser = baseConfig();
browser.output.libraryTarget = "var";
browser.output.filename = "./dist/seng-boilerplate.js";
browser.output.path = path.join(__dirname, '../dist');
browser.entry = [serverURI, browser.entry];

browser.devtool = 'source-map';
browser.watch = true;
browser.progress = true;
browser.keepalive = true;

const compiler = webpack(browser);
const server = new webpackDevServer(compiler, {
	contentBase: "example/"
});

server.listen(port, function(err) {
	if (err) {
		console.log(err);
		return
	}
	console.log(`Listening at http://localhost:${port}\n`);
});

var webpack = require("webpack");
var webpackDevServer = require('webpack-dev-server');
var path = require('path');
var baseConfig = require('../config/webpack.config.dist');

var port = 8080;
var serverURI = `webpack-dev-server/client?http://localhost:${port}/`;

var browser = baseConfig();
browser.output.libraryTarget = "var";
browser.output.filename = "./dist/seng-boilerplate.js";
browser.output.path = path.join(__dirname, '../dist');
browser.entry = [serverURI, browser.entry];

browser.devtool = 'source-map';
browser.watch = true;
browser.progress = true;
browser.keepalive = true;

var compiler = webpack(browser);
var server = new webpackDevServer(compiler, {
	contentBase: "example/"
});

server.listen(port, function(err) {
	if (err) {
		console.log(err);
		return
	}
	console.log(`Listening at http://localhost:${port}\n`);
});

Remove `let`/`const` to support node 4


import { Model as AgentMixin, defineProjections } from '../mixins/regenerated/models/i-c-s-soft-s-t-o-r-m-n-e-t-security-agent';
import BaseModel from './model';
import OfflineModelMixin from '../mixins/offline-model';

let Model = BaseModel.extend(OfflineModelMixin, AgentMixin);
defineProjections(Model);

export default Model;

import { Model as AgentMixin, defineProjections } from '../mixins/regenerated/models/i-c-s-soft-s-t-o-r-m-n-e-t-security-agent';
import BaseModel from './model';

let Model = BaseModel.extend(AgentMixin);
defineProjections(Model);

export default Model;

Fix agent model disable offline audit


var pagination = require('hexo-pagination');
var _ = require('lodash');

hexo.extend.generator.register('category', function(locals){
  var config = this.config;
  var categories = locals.data.categories;
  if (config.category_generator) {
    var perPage = config.category_generator.per_page;
  } else {
    var perPage = 10;
  }
  var paginationDir = config.pagination_dir || 'page';
  var result = [];

  _.each(categories, function(data, title) {
    _.each(data, function(data, lang) {
      result = result.concat(
        pagination(lang + '/' + data.slug, getCategoryByName(locals.categories, data.category).posts, {
          perPage: perPage,
          layout: ['category', 'archive', 'index'],
          format: paginationDir + '/%d/',
          data: {
            lang: lang,
            title: data.name
          }
        })
      );
    });
  });

  return result;
});

function getCategoryByName(categories, name) {
  return categories.toArray().filter(function(category){
    return category.name == name;
  })[0];
}

var pagination = require('hexo-pagination');
var _ = require('lodash');

hexo.extend.generator.register('category', function(locals){
  var config = this.config;
  var categories = locals.data.categories;
  if (config.category_generator) {
    var perPage = config.category_generator.per_page;
  } else {
    var perPage = 10;
  }
  var paginationDir = config.pagination_dir || 'page';
  var result = [];

  _.each(categories, function(data, title) {
    _.each(data, function(data, lang) {
      result = result.concat(
        pagination(lang + '/' + data.slug, getCategoryByName(locals.categories, data.category).posts, {
          perPage: perPage,
          layout: ['category', 'archive', 'index'],
          format: paginationDir + '/%d/',
          data: {
            lang: lang,
            title: data.name,
            category: data.category
          }
        })
      );
    });
  });

  return result;
});

function getCategoryByName(categories, name) {
  return categories.toArray().filter(function(category){
    return category.name == name;
  })[0];
}

Add category as category page variable


window.GOVUK = window.GOVUK || {}
window.GOVUK.Modules = window.GOVUK.Modules || {};

(function (global, GOVUK) {
  'use strict'

  GOVUK.Modules.TrackBrexitQaChoices = function () {
    this.start = function (element) {
      track(element)
    }

    function track (element) {
      element.on('submit', function (event) {
        var $checkedOption, eventLabel, options
        var $submittedForm = event.target
        var $checkedOptions = $submittedForm.querySelectorAll('input:checked')
        var questionKey = $submittedForm.data('question-key')

        if ($checkedOptions.length) {
          $checkedOptions.each(function (index) {
            $checkedOption = $(this)
            var checkedOptionId = $checkedOption.attr('id')
            var checkedOptionLabel = $submittedForm.find('label[for="' + checkedOptionId + '"]').text().trim()
            eventLabel = checkedOptionLabel.length
              ? checkedOptionLabel
              : $checkedOption.val()

            options = { transport: 'beacon', label: eventLabel }

            GOVUK.SearchAnalytics.trackEvent('brexit-checker-qa', questionKey, options)
          })
        } else {
          // Skipped questions
          options = { transport: 'beacon', label: 'no choice' }

          GOVUK.SearchAnalytics.trackEvent('brexit-checker-qa', questionKey, options)
        }
      })
    }
  }
})(window, window.GOVUK)

window.GOVUK = window.GOVUK || {}
window.GOVUK.Modules = window.GOVUK.Modules || {};

(function (global, GOVUK) {
  'use strict'

  GOVUK.Modules.TrackBrexitQaChoices = function () {
    this.start = function (element) {
      track(element)
    }

    function track (element) {
      element.on('submit', function (event) {
        var eventLabel, options
        var $submittedForm = event.target
        var $checkedOptions = $submittedForm.querySelectorAll('input:checked')
        var questionKey = $submittedForm.data('question-key')

        if ($checkedOptions.length) {
          for (var i = 0; i < $checkedOptions.length; i++) {
            var checkedOptionId = $checkedOptions[i].getAttribute('id')
            var checkedOptionLabel = $submittedForm.find('label[for="' + checkedOptionId + '"]').text().trim()
            eventLabel = checkedOptionLabel.length
              ? checkedOptionLabel
              : $checkedOptions[i].val()

            options = { transport: 'beacon', label: eventLabel }

            GOVUK.SearchAnalytics.trackEvent('brexit-checker-qa', questionKey, options)
          }
        } else {
          // Skipped questions
          options = { transport: 'beacon', label: 'no choice' }

          GOVUK.SearchAnalytics.trackEvent('brexit-checker-qa', questionKey, options)
        }
      })
    }
  }
})(window, window.GOVUK)

Replace jQuery `each` method with for loop


'use strict';

/**@type {{[k: string]: ModdedTemplateData}} */
let BattlePokedex = {
	rotomheat: {
		inherit: true,
		types: ["Electric", "Ghost"],
	},
	rotomwash: {
		inherit: true,
		types: ["Electric", "Ghost"],
	},
	rotomfrost: {
		inherit: true,
		types: ["Electric", "Ghost"],
	},
	rotomfan: {
		inherit: true,
		types: ["Electric", "Ghost"],
	},
	rotommow: {
		inherit: true,
		types: ["Electric", "Ghost"],
	},
};

exports.BattlePokedex = BattlePokedex;

'use strict';

/**@type {{[k: string]: ModdedTemplateData}} */
let BattlePokedex = {
	milotic: {
		inherit: true,
		evoType: 'levelExtra',
		evoCondition: 'with high Beauty',
	},
	rotomheat: {
		inherit: true,
		types: ["Electric", "Ghost"],
	},
	rotomwash: {
		inherit: true,
		types: ["Electric", "Ghost"],
	},
	rotomfrost: {
		inherit: true,
		types: ["Electric", "Ghost"],
	},
	rotomfan: {
		inherit: true,
		types: ["Electric", "Ghost"],
	},
	rotommow: {
		inherit: true,
		types: ["Electric", "Ghost"],
	},
};

exports.BattlePokedex = BattlePokedex;

Mark Feebas's evolution in Gen4 as requiring high Beauty


/* jshint node: true */
'use strict';

/**
  ## cog/throttle

  ```js
  var throttle = require('cog/throttle');
  ```

  ### throttle(fn, delay)

  A cherry-pickable throttle function.  Used to throttle `fn` to ensure
  that it can be called at most once every `delay` milliseconds.  Will
  fire first event immediately, ensuring the next event fired will occur
  at least `delay` milliseconds after the first, and so on.

**/
module.exports = function(fn, delay) {
  var lastExec = 0;
  var timer;
  var queuedArgs;
  var queuedScope;

  function invokeDefered() {
    fn.apply(queuedScope, queuedArgs || []);
    lastExec = Date.now();
  }

  return function() {
    var tick = Date.now();
    var elapsed = tick - lastExec;

    // always clear the defered timer
    clearTimeout(timer);

    if (elapsed < delay) {
      queuedArgs = [].slice.call(arguments, 0);
      queuedScope = this;

      return timer = setTimeout(invokeDefered, delay - elapsed);
    }

    // call the function
    lastExec = tick;
    fn.apply(this, arguments);
  };
};

/* jshint node: true */
'use strict';

/**
  ## cog/throttle

  ```js
  var throttle = require('cog/throttle');
  ```

  ### throttle(fn, delay, opts)

  A cherry-pickable throttle function.  Used to throttle `fn` to ensure
  that it can be called at most once every `delay` milliseconds.  Will
  fire first event immediately, ensuring the next event fired will occur
  at least `delay` milliseconds after the first, and so on.

**/
module.exports = function(fn, delay, opts) {
  var lastExec = (opts || {}).leading !== false ? 0 : Date.now();
  var trailing = (opts || {}).trailing;
  var timer;
  var queuedArgs;
  var queuedScope;

  // trailing defaults to true
  trailing = trailing || trailing === undefined;

  function invokeDefered() {
    fn.apply(queuedScope, queuedArgs || []);
    lastExec = Date.now();
  }

  return function() {
    var tick = Date.now();
    var elapsed = tick - lastExec;

    // always clear the defered timer
    clearTimeout(timer);

    if (elapsed < delay) {
      queuedArgs = [].slice.call(arguments, 0);
      queuedScope = this;

      return trailing && (timer = setTimeout(invokeDefered, delay - elapsed));
    }

    // call the function
    lastExec = tick;
    fn.apply(this, arguments);
  };
};

Add trailing & leading opts as per underscore.js implementation


/**
 *
 *  Copyright 2016 Netflix, Inc.
 *
 *     Licensed under the Apache License, Version 2.0 (the "License");
 *     you may not use this file except in compliance with the License.
 *     You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *     Unless required by applicable law or agreed to in writing, software
 *     distributed under the License is distributed on an "AS IS" BASIS,
 *     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *     See the License for the specific language governing permissions and
 *     limitations under the License.
 *
 */
const DEPTH = {
  normalNode: -5000, // Moves more negative
  normalConnection: -9999, // Stays static
  dimmedNode: -10000, // Moves more negative
  dimmedConnection: -14999, // Stays static
};

export default {
  DEPTH: DEPTH
};

/**
 *
 *  Copyright 2016 Netflix, Inc.
 *
 *     Licensed under the Apache License, Version 2.0 (the "License");
 *     you may not use this file except in compliance with the License.
 *     You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *     Unless required by applicable law or agreed to in writing, software
 *     distributed under the License is distributed on an "AS IS" BASIS,
 *     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *     See the License for the specific language governing permissions and
 *     limitations under the License.
 *
 */
const DEPTH = {
  normalNode: -5000, // Moves more negative
  normalConnection: -9999, // Stays static
  dimmedNode: -15000, // Moves more negative
  dimmedConnection: -19999, // Stays static
};

export default {
  DEPTH: DEPTH
};

Fix hover depth for connections


let gulp = require('gulp'),
    exec = require('exec'),
    watch = require('gulp-watch');

let ADD = 'add';

let paths = {
  jobs: ['../uploads/**/*.fds'],
  parcel: ['../parcel.php']
};

//var runCommand = "php -r 'require \"" + paths.parcel + "\"; P::run();'";

gulp.task('jobs', function () {

});

gulp.task('watch', function() {
  watch(paths.jobs, function (vinyl) {
    if (vinyl.event == ADD)
      console.log("Houston, we have a new FDS job");
  });
});

gulp.task('default', ['watch']);

var gulp = require('gulp'),
    exec = require('exec'),
    watch = require('gulp-watch');

const ADD = 'add';

var paths = {
  jobs: ['../uploads/**/*.fds'],
  parcel: ['../parcel.php']
};

//var runCommand = "php -r 'require \"" + paths.parcel + "\"; P::run();'";

gulp.task('jobs', function () {

});

gulp.task('watch', function() {
  watch(paths.jobs, function (vinyl) {
    if (vinyl.event == ADD)
      console.log("Houston, we have a new FDS job");
  });
});

gulp.task('default', ['watch']);

Change let to var declarations


import map from 'lodash/map';
import { ExamResource, ContentNodeResource } from 'kolibri.resources';

export function fetchQuizSummaryPageData(examId) {
  const payload = {
    // To display the title, status, etc. of the Quiz
    exam: {},
    // To render the exercises in QuestionListPreview > ContentRenderer
    exerciseContentNodes: {},
  };
  return ExamResource.fetchModel({ id: examId }).then(exam => {
    payload.exam = exam;
    return ContentNodeResource.fetchCollection({
      getParams: {
        ids: map(exam.question_sources, 'exercise_id'),
      },
    }).then(contentNodes => {
      payload.exerciseContentNodes = contentNodes;
      return payload;
    });
  });
}

export function serverAssignmentPayload(listOfIDs, classId) {
  const assignedToClass = listOfIDs.length === 0 || listOfIDs[0] === classId;
  if (assignedToClass) {
    return [{ collection: classId }];
  }
  return listOfIDs.map(id => {
    return { collection: id };
  });
}

export function clientAssigmentState(listOfIDs, classId) {
  const assignedToClass = listOfIDs.length === 0 || listOfIDs[0] === classId;
  if (assignedToClass) {
    return [];
  }
  return listOfIDs;
}

export function deleteExam(examId) {
  return ExamResource.deleteModel({ id: examId });
}

import map from 'lodash/map';
import { fetchNodeDataAndConvertExam } from 'kolibri.utils.exams';
import { ExamResource, ContentNodeResource } from 'kolibri.resources';

export function fetchQuizSummaryPageData(examId) {
  const payload = {
    // To display the title, status, etc. of the Quiz
    exam: {},
    // To render the exercises in QuestionListPreview > ContentRenderer
    exerciseContentNodes: {},
  };
  return ExamResource.fetchModel({ id: examId })
    .then(exam => {
      return fetchNodeDataAndConvertExam(exam);
    })
    .then(exam => {
      payload.exam = exam;
      return ContentNodeResource.fetchCollection({
        getParams: {
          ids: map(exam.question_sources, 'exercise_id'),
        },
      }).then(contentNodes => {
        payload.exerciseContentNodes = contentNodes;
        return payload;
      });
    });
}

export function serverAssignmentPayload(listOfIDs, classId) {
  const assignedToClass = listOfIDs.length === 0 || listOfIDs[0] === classId;
  if (assignedToClass) {
    return [{ collection: classId }];
  }
  return listOfIDs.map(id => {
    return { collection: id };
  });
}

export function clientAssigmentState(listOfIDs, classId) {
  const assignedToClass = listOfIDs.length === 0 || listOfIDs[0] === classId;
  if (assignedToClass) {
    return [];
  }
  return listOfIDs;
}

export function deleteExam(examId) {
  return ExamResource.deleteModel({ id: examId });
}

Convert quiz question_sources in fetchQuizSummaryPageData


var RecipeListView = function (recipes) {

    var recipes;

    this.initialize = function() {
        this.$el = $('#content');
        if(recipes[0] !== undefined)
            this.render();
    };

    this.setRecipes = function(list) {
        recipes = list;
        this.render();
    }

    this.render = function() {
        this.$el.html(this.template(recipes));
        return this;
    };

    this.initialize();

}

var RecipeListView = function (recipes) {

    this.initialize = function() {
        this.$el = $('#content');
        if(recipes[0] !== undefined)
            this.render();
    };

    this.setRecipes = function(list) {
        recipes = list;
        this.render();
    }

    this.render = function() {
        this.$el.html(this.template(recipes));
        return this;
    };

    this.initialize();

}

Remove local recipes var in recipe list view


import Ember from 'ember';

export default Ember.Route.extend({
    model: function() {
        return Ember.Object.create({
           'PAGINATION_DISPLAYING': 'Displaying',
           'DEVICE_LIST_PAGINATION_LABEL': 'Viewing {0} to {1} of {2} Devices',
           'DEVICE_LIST_PAGINATION_PER_PAGE': ' per page'
        });
    },

    setupController: function( controller, model ) {
        this._super.apply( this, arguments );

        this.controllerFor( 'pagination' ).get( 'translateService' ).setDictionary( model );
    }
});

import Ember from 'ember';

export default Ember.Route.extend({
    setupController: function() {
        this.controllerFor( 'pagination' ).get( 'translateService' ).setDictionary({
           'PAGINATION_DISPLAYING'           : 'Displaying',
           'DEVICE_LIST_PAGINATION_LABEL'    : 'Viewing {0} to {1} of {2} Devices',
           'DEVICE_LIST_PAGINATION_PER_PAGE' : ' per page'
        });
    }
});

Refactor to resolve odd ArrayProxy errors on sl-tab-panel route


import {load} from "Injector";
import A from "example/A";
import D from "example/D";
import assert from "./assert";
import Context from "./di/Context";

const d = load(D, {name:'injected instance'});
const context = new Context({[D]: d});

const a1 = load(A, context);
const a2 = load(A, context);
const a3 = load(A, {[D]: 'test'});

assert.equal(a1.d, a2.d);
assert.equal(a1.b, a2.b);
assert.equal(a1.c, a2.c);
assert.equal(a1.b.c.d, a2.b.c.d);

assert.notEqual(a1.d, a3.d);
assert.notEqual(a1.b, a3.b);
assert.notEqual(a1.c, a3.c);
assert.notEqual(a1.b.c.d, a3.b.c.d);

import {load} from "Injector";
import A from "example/A";
import D from "example/D";
import assert from "./assert";
import Context from "./di/Context";

const d = load(D, {name:'injected instance'});
const context = new Context({[D]: d});

const a1 = load(A, context);
const a2 = load(A, context);
const a3 = load(A, {[D]: 'test'});

assert.equal(a1, a2);
assert.equal(a1.d, a2.d);
assert.equal(a1.b, a2.b);
assert.equal(a1.c, a2.c);
assert.equal(a1.b.c.d, a2.b.c.d);

assert.notEqual(a1, a3);
assert.notEqual(a1.d, a3.d);
assert.notEqual(a1.b, a3.b);
assert.notEqual(a1.c, a3.c);
assert.notEqual(a1.b.c.d, a3.b.c.d);

Add reference tests for created objects


import Vue from 'vue';
import Vuex from 'vuex';
import VuexPlus from 'vuex+';

Vue.use(Vuex);
Vue.use(VuexPlus.getVuePlugin(Vue));

// Create the Vuex store
const store = new Vuex.Store({
  plugins: [VuexPlus.getVuexPlugin(Vuex)],
  strict: process.env.NODE_ENV !== 'production',
});

/* eslint-disable */
new Vue({
  el: '#app',
  store,
  render: h => h(require('./app.vue')),
});

import Vue from 'vue';
import Vuex from 'vuex';
import VuexPlus from 'vuex+';

Vue.use(Vuex);
Vue.use(VuexPlus.getVuePlugin(Vue));

// Create the Vuex store
const store = new Vuex.Store({
  plugins: [VuexPlus.getVuexPlugin(Vuex)],
  strict: process.env.NODE_ENV !== 'production',
});

/* eslint-disable */
new Vue({
  el: '#app',
  store,
  render: h => h(require('./app.vue').default),
});

Fix for new vue module handling


const http = require('http');
const _ = require('lodash');

// This reponder is assuming that all <500 errors are safe to be responded
// with their .message attribute.
// DO NOT write sensitive data into error messages.
function createErrorResponder(_opts) {
  const opts = _.merge({
    isErrorSafeToRespond: status => status < 500,
  }, _opts);

  // 4 params needed for Express to know it's a error handler middleware
  // eslint-disable-next-line
  return function errorResponder(err, req, res, next) {
    let message;
    let status = err.status ? err.status : 500;
    switch (err.type) {
      case 'StripeCardError':
        // A declined card error
        status = 402;
        break;
      case 'StripeInvalidRequestError':
        status = 402;
        break;
      case 'StripeConnectionError':
        status = 503;
        break;
      case 'StripeRateLimitError':
        status = 429;
        break;
      default:
        break;
    }

    const httpMessage = http.STATUS_CODES[status];
    if (opts.isErrorSafeToRespond(status)) {
      // eslint-disable-next-line
      message = err.message;
    } else {
      message = httpMessage;
    }

    const isPrettyValidationErr = _.has(err, 'errors');
    const body = isPrettyValidationErr
      ? JSON.stringify(err)
      : { status, statusText: httpMessage, messages: [message] };

    res.status(status);
    res.send(body);
  };
}

module.exports = createErrorResponder;

const http = require('http');
const _ = require('lodash');

// This reponder is assuming that all <500 errors are safe to be responded
// with their .message attribute.
// DO NOT write sensitive data into error messages.
function createErrorResponder(_opts) {
  const opts = _.merge({
    isErrorSafeToRespond: status => status < 500,
  }, _opts);

  // 4 params needed for Express to know it's a error handler middleware
  // eslint-disable-next-line
  return function errorResponder(err, req, res, next) {
    let message;
    const status = err.status ? err.status : 500;

    const httpMessage = http.STATUS_CODES[status];
    if (opts.isErrorSafeToRespond(status)) {
      // eslint-disable-next-line
      message = err.message;
    } else {
      message = httpMessage;
    }

    const isPrettyValidationErr = _.has(err, 'errors');
    const body = isPrettyValidationErr
      ? JSON.stringify(err)
      : { status, statusText: httpMessage, messages: [message] };

    res.status(status);
    res.send(body);
  };
}

module.exports = createErrorResponder;

Remove unnecessary stripe status checks


  var module;
  return function(src, options) {
    options = options || {};
    var format = options.format || "svg";
    var engine = options.engine || "dot";
    if (typeof module === "undefined") {
      module = Module();
    }
    return module["ccall"]("vizRenderFromString", "string", ["string", "string", "string"], [src, format, engine]);
  }
})();

  var graphviz;

  return function(src) {
    var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
    var format = options.format === undefined ? "svg" : options.format;
    var engine = options.engine === undefined ? "dot" : options.engine;

    if (typeof graphviz === "undefined") {
      graphviz = Module();
    }

    return graphviz["ccall"]("vizRenderFromString", "string", ["string", "string", "string"], [src, format, engine]);
  }
})();

if (typeof module !== "undefined" && typeof module.exports !== 'undefined') {
  module.exports = Viz;
}

Clean up wrapper and add Node export.


import React, { Component } from 'react';
import Section from 'shared/components/section/section';
import ClipPathImage from 'shared/components/clipPathImage/clipPathImage';
import familyImage from 'images/Family-1.jpg';
import milImage from 'images/Mil-1.jpg';
import volunteerImage from 'images/Volunteer-1.jpg';

import styles from './moreInformation.css';

class MoreInformation extends Component {
  render() {
    return (

          <ClipPathImage
            title="Military Families and Spouses"
            image={familyImage}
            altText="Military Families and Spouses"
          />
          <ClipPathImage
            title="Veterans, Active Duty, and Reservists"
            image={milImage}
            altText="Veterans, Active Duty, and Reservists"
          />
          <ClipPathImage
            title="Volunteers and Sponsors"
            image={volunteerImage}
            altText="Volunteers and Sponsors"
          />

    );
  }
}

export default MoreInformation;

Replace "More Information" with "Who We Serve"


"use strict";

// The DOM really should provide this for you, so you don't have to
// keep reimplementing it.

function RoostEventTarget() {
  this.listeners_ = {};
};
RoostEventTarget.prototype.addEventListener = function(type, cb) {
  if (!(type in this.listeners_))
    this.listeners_[type] = [];
  if (this.listeners_[type].indexOf(cb) == -1)
    this.listeners_[type].push(cb);
};
RoostEventTarget.prototype.removeEventListener = function(type, cb) {
  if (!(type in this.listeners_))
    return;
  var idx = this.listeners_[type].indexOf(cb);
  if (idx == -1)
    return;
  this.listeners_[type].splice(idx, 1);
};
RoostEventTarget.prototype.dispatchEvent = function(ev) {
  var type = ev.type;
  if (type in this.listeners_) {
    for (var i = 0; i < this.listeners_[type].length; i++) {
      this.listeners_[type][i].call(this, ev);
    }
  }
};

"use strict";

// The DOM really should provide this for you, so you don't have to
// keep reimplementing it.

function RoostEventTarget() {
  this.listeners_ = {};
};
RoostEventTarget.prototype.indexOfListener_ = function(type, cb) {
  if (!(type in this.listeners_))
    return -1;
  for (var i = 0; i < this.listeners_[type].length; i++) {
    if (this.listeners_[type][i].cb === cb)
      return i;
  }
  return -1;
};
RoostEventTarget.prototype.addEventListener = function(type, cb) {
  if (!(type in this.listeners_))
    this.listeners_[type] = [];
  if (this.indexOfListener_(type, cb) == -1)
    this.listeners_[type].push({cb: cb, doomed: false});
};
RoostEventTarget.prototype.removeEventListener = function(type, cb) {
  if (!(type in this.listeners_))
    return;
  var idx = this.indexOfListener_(type, cb);
  if (idx == -1)
    return;
  // Removing an event listener /does/ affect current dispatches.
  this.listeners_[type][idx].doomed = true;
  this.listeners_[type].splice(idx, 1);
};
RoostEventTarget.prototype.dispatchEvent = function(ev) {
  var type = ev.type;
  if (type in this.listeners_) {
    // Make a copy of the list; adding an event listener mid-dispatch
    // does /not/ run it.
    var listeners = this.listeners_[type].slice(0);
    for (var i = 0; i < listeners.length; i++) {
      if (!listeners[i].doomed)
        listeners[i].cb.call(this, ev);
    }
  }
};

Make RoostEventTarget behave properly for adding/removing mid-dispatch


'use strict';

/**
 * Account creation event
 */
module.exports = (srcPath) => {
  const Account = require(srcPath + 'Account');
  const EventUtil = require(srcPath + 'EventUtil');

  return {
    event: (state) => (socket, name) => {
      const write = EventUtil.genWrite(socket);
      const say = EventUtil.genSay(socket);

      let newAccount = null;
      write(`<bold>Do you want your account's username to be ${name}?</bold> <cyan>[y/n]</cyan> `);

      socket.once('data', data => {
        data = data.toString('').trim();

        data = data.toLowerCase();
        if (data === 'y' || data === 'yes') {
          say('Creating account...');
          newAccount = new Account({
            username: name
          });

          return socket.emit('change-password', socket, {
            account: newAccount,
            nextStage: 'create-player'
          });
        } else if (data && data === 'n' || data === 'no') {
          say("Let's try again!");

          return socket.emit('login', socket);
        }

        return socket.emit('create-account', socket, name);
      });
    }
  };
};

'use strict';

/**
 * Account creation event
 */
module.exports = (srcPath) => {
  const Account = require(srcPath + 'Account');
  const EventUtil = require(srcPath + 'EventUtil');

  return {
    event: (state) => (socket, name) => {
      const write = EventUtil.genWrite(socket);
      const say = EventUtil.genSay(socket);

      let newAccount = null;
      write(`<bold>Do you want your account's username to be ${name}?</bold> <cyan>[y/n]</cyan> `);

      socket.once('data', data => {
        data = data.toString('utf8').trim();

        data = data.toLowerCase();
        if (data === 'y' || data === 'yes') {
          say('Creating account...');
          newAccount = new Account({
            username: name
          });

          return socket.emit('change-password', socket, {
            account: newAccount,
            nextStage: 'create-player'
          });
        } else if (data && data === 'n' || data === 'no') {
          say("Let's try again!");

          return socket.emit('login', socket);
        }

        return socket.emit('create-account', socket, name);
      });
    }
  };
};

Fix crash during account creation with node version 8


var ffi = require('node-ffi')
  , core = require('./core')
  , types = require('./types')
  , Pointer = ffi.Pointer
  , SIZE_MAP = ffi.Bindings.TYPE_SIZE_MAP
  , FUNC_MAP = ffi.TYPE_TO_POINTER_METHOD_MAP

/**
 * Returns a new Pointer that points to this pointer.
 * Equivalent to the "address of" operator:
 *   type* = &ptr
 */
Pointer.prototype.ref = function ref () {
  var ptr = new Pointer(SIZE_MAP.pointer)
  ptr.putPointer(this)
  ptr._type = '^' + this._type
  return ptr
}

/**
 * Dereferences the pointer. Includes wrapping up id instances when necessary.
 * Equivalent to the "value at" operator:
 *   type = *ptr
 */
Pointer.prototype.deref = function deref () {
  var t = this._type
  if (t[0] !== '^') throw new Error('cannot dereference non-pointer')
  // since we're dereferencing, remove the leading ^ char
  t = t.substring(1)
  var ffiType = types.map(t)
    , val = this['get' + FUNC_MAP[ffiType] ]()
  val._type = t
  return core.wrapValue(val, t)
}

var ffi = require('node-ffi')
  , core = require('./core')
  , types = require('./types')
  , Pointer = ffi.Pointer
  , SIZE_MAP = ffi.Bindings.TYPE_SIZE_MAP
  , FUNC_MAP = ffi.TYPE_TO_POINTER_METHOD_MAP

// We include a polyfil for `process.arch` on node 0.4.x
if (!process.arch) {
  process.arch = ffi.Bindings.POINTER_SIZE == 8 ? 'x64' : 'ia32'
}

/**
 * Returns a new Pointer that points to this pointer.
 * Equivalent to the "address of" operator:
 *   type* = &ptr
 */
Pointer.prototype.ref = function ref () {
  var ptr = new Pointer(SIZE_MAP.pointer)
  ptr.putPointer(this)
  ptr._type = '^' + this._type
  return ptr
}

/**
 * Dereferences the pointer. Includes wrapping up id instances when necessary.
 * Equivalent to the "value at" operator:
 *   type = *ptr
 */
Pointer.prototype.deref = function deref () {
  var t = this._type
  if (t[0] !== '^') throw new Error('cannot dereference non-pointer')
  // since we're dereferencing, remove the leading ^ char
  t = t.substring(1)
  var ffiType = types.map(t)
    , val = this['get' + FUNC_MAP[ffiType] ]()
  val._type = t
  return core.wrapValue(val, t)
}

Add a polyfil for `process.arch` on node 0.4.x.


import React from 'react';
import firebase from 'firebase';
import ReactFireMixin from 'reactfire';

const ChatMessage = ({ time, name, message }) => {
  return
{time} {name}: {message}

};

const Chat = React.createClass({

  mixins: [ReactFireMixin],

  getInitialState() {
    return {
      messages: [],
      message: '',
      chatRef: firebase.database().ref(`/videos/${this.props.videoKey}/chat`)
    };
  },

  setValue(propName, value) {
    this.setState({
      [propName]: value
    })
  },

  componentDidMount() {
    this.bindAsArray(this.state.chatRef, 'messages')
  },

  postMessage(e) {
    e.preventDefault();

    this.state.chatRef.push({
      time: new Date().toDateString(),
      message: this.state.message,
      name: "Someone"
    });
  },

  render() {
    return (

        <form onSubmit={ e => this.postMessage(e) }>
          <input
            type="text"
            placeholder="add message"
            onChange={ e => this.setValue('message', e.target.value) } />
          <button type="submit">Submit</button>
        </form>

          {this.state.messages.map((message, index) => <ChatMessage key={index} {...message} /> ) }

    )
  }
});

export default Chat;

import React from 'react';
import firebase from 'firebase';
import ReactFireMixin from 'reactfire';

const ChatMessage = ({ time, name, message }) => {
  return
{time} {name}: {message}

};

const Chat = React.createClass({

  mixins: [ReactFireMixin],

  getInitialState() {
    return {
      messages: [],
      message: '',
      chatRef: firebase.database().ref(`/chats/${this.props.videoKey}`)
    };
  },

  componentDidMount() {
    this.bindAsArray(this.state.chatRef, 'messages')
  },

  postMessage(e) {
    e.preventDefault();

    this.state.chatRef.push({
      time: new Date().toDateString(),
      message: this.state.message,
      name: "Someone"
    });
  },

  render() {
    return (

        <form onSubmit={ e => this.postMessage(e) }>
          <input
            type="text"
            placeholder="add message"
            onChange={ e => this.setState({ message: e.target.value }) }/>
          <button type="submit">Submit</button>
        </form>

          {this.state.messages.map((message, index) => <ChatMessage key={index} {...message} />) }

    )
  }
});

export default Chat;

Move chat messages to separate collection


'use strict';

module.exports = null;

var ipcRenderer;
try {
  ipcRenderer = require('electron').ipcRenderer;
} catch (e) {
  ipcRenderer = null;
}

var originalConsole = require('./lib/original-console');

if (ipcRenderer) {
  module.exports = {
    error:   log.bind(null, 'error'),
    warn:    log.bind(null, 'warn'),
    info:    log.bind(null, 'info'),
    verbose: log.bind(null, 'verbose'),
    debug:   log.bind(null, 'debug'),
    silly:   log.bind(null, 'silly'),
    log:     log.bind(null, 'info')
  };

  module.exports.default = module.exports;

  ipcRenderer.on('__ELECTRON_LOG_RENDERER__', function(event, level, text) {
    if (level === 'verbose') {
      level = 'log';
    } else if (level === 'silly') {
      level = 'debug';
    }

    originalConsole[level].call(originalConsole.context, text);
  });
}

function log() {
  var data = Array.prototype.slice.call(arguments);

  data = data.map(function(obj) {
    if (obj instanceof Error) {
      obj = obj.stack || obj;
    }

    return obj;
  });

  ipcRenderer.send('__ELECTRON_LOG__', data);
}

'use strict';

module.exports = null;

var ipcRenderer;
try {
  ipcRenderer = require('electron').ipcRenderer;
} catch (e) {
  ipcRenderer = null;
}

var originalConsole = require('./lib/original-console');

if (ipcRenderer) {
  module.exports = {
    error:   log.bind(null, 'error'),
    warn:    log.bind(null, 'warn'),
    info:    log.bind(null, 'info'),
    verbose: log.bind(null, 'verbose'),
    debug:   log.bind(null, 'debug'),
    silly:   log.bind(null, 'silly'),
    log:     log.bind(null, 'info')
  };

  module.exports.default = module.exports;

  ipcRenderer.on('__ELECTRON_LOG_RENDERER__', function(event, level, text) {
    if (level === 'verbose') {
      level = 'log';
    } else if (level === 'silly') {
      level = 'debug';
    }
    let msg = '';
    let args = [];
    if (Array.isArray(text)) {
      msg = text.shift();
      args = text;
    } else {
      msg = text;
    }
    originalConsole[level].call(originalConsole.context, msg, ...args);
  });
}

function log() {
  var data = Array.prototype.slice.call(arguments);

  data = data.map(function(obj) {
    if (obj instanceof Error) {
      obj = obj.stack || obj;
    }

    return obj;
  });

  ipcRenderer.send('__ELECTRON_LOG__', data);
}

Allow color formatting in dev console


/* globals __DEV__ */
import Phaser from 'phaser'
import Mushroom from '../sprites/Mushroom'
import Car from '../sprites/Car'

export default class extends Phaser.State {
    init () {}
    preload () {}

    create () {
        const bannerText = 'Phaser + ES6 + Webpack'
        let banner = this.add.text(this.world.centerX, this.game.height - 80, bannerText)
        banner.font = 'Bangers'
        banner.padding.set(10, 16)
        banner.fontSize = 40
        banner.fill = '#77BFA3'
        banner.smoothed = false
        banner.anchor.setTo(0.5)

        this.mushroom = new Mushroom({
            game: this,
            x: this.world.centerX,
            y: this.world.centerY,
            asset: 'mushroom',
        });

        this.car = new Car({
            game: this,
            x: this.world.centerX,
            y: this.world.centerY,
            asset: 'car',
        });

        this.game.add.existing(this.mushroom);
        this.game.add.existing(this.car);
    }

    update () {

    }

    render () {
        if (__DEV__) {
            this.game.debug.spriteInfo(this.mushroom, 32, 32)
        }
    }
}

/* globals __DEV__ */
import Phaser from 'phaser'
import Mushroom from '../sprites/Mushroom'
import Car from '../sprites/Car'
import {gameWidth, gameHeight} from '../config.js'

export default class extends Phaser.State {
  init () {}
  preload () {}

  create () {
    game.world.setBounds(0, 0, 3000, 3000);
    const bannerText = 'Phaser + ES6 + Webpack';
    let banner = this.add.text(this.world.centerX, this.game.height - 80, bannerText);
    banner.font = 'Bangers';
    banner.padding.set(10, 16);
    banner.fontSize = 40;
    banner.fill = '#77BFA3';
    banner.smoothed = false;
    banner.anchor.setTo(0.5);

    this.mushroom = new Mushroom({
      game: this,
      x: this.world.centerX,
      y: this.world.centerY,
      asset: 'mushroom',
    });

    this.car = new Car({
      game: this,
      x: this.world.centerX,
      y: this.world.centerY,
      asset: 'car',
    });

    this.game.add.existing(this.mushroom);
    this.game.add.existing(this.car);
  }

  update () {
    game.camera.x = this.car.x - game.width/2;
    game.camera.y = this.car.y - game.height/2;
  }

  render () {
    if (__DEV__) {
      this.game.debug.cameraInfo(game.camera, 32, 32);
    }
  }
}

Make camera follow the car object


function updateFormForState() {
    var v = $("new-mode-selector").value
    if ("" == v) {
        $("new-date-input-group").hide()
        $("new-reason-input-group").hide()
        if (typeof($("new-mode-submit")) != 'undefined') $("new-mode-submit").hide()
    } else if (3 == v) {
        $("new-date-input-group").hide()
        $("new-reason-input-group").show()
        if (typeof($("new-mode-submit")) != 'undefined') $("new-mode-submit").show()
    } else if (1 == v){
        $("new-date-input-group").show()
        $("new-reason-input-group").show()
        if (typeof($("new-mode-submit")) != 'undefined') $("new-mode-submit").show()
    } else if (2 == v) {
        $("new-date-input-group").hide()
        $("new-reason-input-group").hide()
        if (typeof($("new-mode-submit")) != 'undefined') $("new-mode-submit").show()
    }
}

function registerStateBasedFormMutator() {
    Event.observe("new-mode-selector", "change", updateFormForState)
}

Event.observe(window, "load", registerStateBasedFormMutator)
Event.observe(window, "load", updateFormForState)

function updateFormForState() {
    var v = $("new-mode-selector").value
    if ("" == v) {
        $("new-date-input-group").hide()
        $("new-reason-input-group").hide()
        if ($("new-mode-submit") != null) $("new-mode-submit").hide()
    } else if (3 == v) {
        $("new-date-input-group").hide()
        $("new-reason-input-group").show()
        if ($("new-mode-submit") != null) $("new-mode-submit").show()
    } else if (1 == v){
        $("new-date-input-group").show()
        $("new-reason-input-group").show()
        if ($("new-mode-submit") != null) $("new-mode-submit").show()
    } else if (2 == v) {
        $("new-date-input-group").hide()
        $("new-reason-input-group").hide()
        if ($("new-mode-submit") != null) $("new-mode-submit").show()
    }
}

function registerStateBasedFormMutator() {
    Event.observe("new-mode-selector", "change", updateFormForState)
}

Event.observe(window, "load", registerStateBasedFormMutator)
Event.observe(window, "load", updateFormForState)

Fix javascript error with no properties for new-mode-submit


Nux
// First the boot, applying a set of rules to
// boot your nux object.
.boot({
	// Boot a full Nux system complete with batteries.
	// refer to nux.extension.kernel
	kernel: true,
	// console logs and test are implemented if required.
	debug: true,
	assetPath: '../src/',
	// Load folder for extension matching the expression
	// {extennsionNamespace}.{extensionName}.js
	extensionPath: "../src/js/nux/extensions/",
	vendorPath: "../src/js/nux/vendor/",

	// Extensions allowed to be executed and implemenred
	// This should only exist in
	// core loaders and baked
	// objects
	allowed: [
	],
	ignoreLog: [ 'wanted',
	'space',
	'receive',
	'run',
	'expected'
	]
}).onReady(function(){
	console.log("Nux ready")
})

$(document).ready(function(){

	$('button.import').click(function(){
		var self = $(this);
		Nux.use(self.text(), function(){
			self.addClass('imported')
		})
	})

})

;Nux
// First the boot, applying a set of rules to
// boot your nux object.
.boot({
	// Boot a full Nux system complete with batteries.
	// refer to nux.extension.kernel
	kernel: false,
	// console logs and test are implemented if required.
	debug: true,
	assetPath: '../src/',
	// Load folder for extension matching the expression
	// {extennsionNamespace}.{extensionName}.js
	extensionPath: "../src/js/nux/extensions/",
	vendorPath: "../src/js/nux/vendor/",
	required: false,
	// Extensions allowed to be executed and implemenred
	// This should only exist in
	// core loaders and baked
	// objects
	allowed: [
	],
	ignoreLog: [ 'space',
	]
}).onReady(function(){
	console.log("Nux ready")
})

Add buttons to perform imports


var gulp = require('gulp');
var server = require('gulp-server-livereload');

gulp.task('default', ['clean', 'scripts'], function() {
  gulp.src('./')
    .pipe(server({
      defaultFile: 'demo.html',
      livereload: true,
      open: true
  }));

  gulp.watch(['./what-input.js', './polyfills/*.js'], ['scripts']);
});

var gulp = require('gulp');
var browserSync = require('browser-sync').create();

gulp.task('default', ['clean', 'scripts'], function() {
  browserSync.init({
    server: {
      baseDir: './'
    }
  });

  gulp.watch(['./what-input.js', './polyfills/*.js'], ['scripts']).on('change', browserSync.reload);
});

Replace server live reload with browser sync


var webpackTS = require('./ts.config');

module.exports = function(options) {
	var webpackLibrary = webpackTS();

	webpackLibrary.entry = options.entry;
	webpackLibrary.output = {
		path: options.path,
		filename: options.filename,
		library: options.library,
		libraryTarget: 'this',
	};
	webpackLibrary.externals = options.externals;

	return webpackLibrary;
};

var webpackTS = require('./ts.config');

module.exports = function(options) {
	var webpackLibrary = webpackTS();

	webpackLibrary.entry = options.entry;
	webpackLibrary.output = {
		path: options.path,
		publicPath: options.publicPath || options.path,
		filename: options.filename,
		library: options.library,
		libraryTarget: 'this',
	};
	webpackLibrary.externals = options.externals;

	return webpackLibrary;
};

Set the public path to the specified public path, or, in the absence of a public path, the path.


/** MIT License (c) copyright 2010-2013 B Cavalier & J Hann */

/**
 * curl json! cram plugin
 */
define(['./jsEncode'], function (jsEncode) {

	return {

		compile: function (pluginId, resId, req, io, config) {
			var absId;

			absId = pluginId + '!' + resId;

			io.read(
				resId,
				function (source) {
					if (config.strictJSONParse) {
						try { JSON.parse(source); } catch (ex) { io.error(ex); }
					}
					// write-out define(id,function(){return{/* json here */}});
					source = 'define("'
						+ absId
						+ '", function () { return '
						+ source
						+ '; });';
					io.write(source);
				},
				io.error
			);
		}
	};

});

/** MIT License (c) copyright 2010-2013 B Cavalier & J Hann */

/**
 * curl json! cram plugin
 */
define(function () {

	return {

		compile: function (pluginId, resId, req, io, config) {
			var absId;

			absId = pluginId + '!' + resId;

			io.read(
				resId,
				function (source) {
					if (config.strictJSONParse) {
						try { JSON.parse(source); } catch (ex) { io.error(ex); }
					}
					// write-out define(id,function(){return{/* json here */}});
					source = 'define("'
						+ absId
						+ '", function () { return '
						+ source
						+ '; });';
					io.write(source);
				},
				io.error
			);
		}
	};

});

REmove unused dependency on jsEncode


(function ($) {
    'use strict';
    var settings;

    $.fn.tuxedoMenu = function (options) {
        var self = this;

        // Extend default settings with options
        settings = $.extend({
            triggerSelector: '.tuxedo-menu-trigger',
            menuSelector: '.tuxedo-menu',
            isFixed: true
        }, options);

        self.addClass('tuxedo-menu tuxedo-menu-pristine animated')
            .toggleClass('tuxedo-menu-visible', !settings.isFixed)
            .toggleClass('tuxedo-menu-fixed slideOutLeft', settings.isFixed);
        $(settings.triggerSelector).addClass('tuxedo-menu-trigger');

        $(settings.triggerSelector).on('click', function () {
            if (!settings.isFixed) {
                return;
            }

            $(settings.menuSelector)
                .toggleClass('slideInLeft slideOutLeft')
                .addClass('tuxedo-menu-visible');
        });

        $(document).click(function (event) {
            if (!settings.isFixed ||
                $(event.target).is(settings.triggerSelector)) {
                return;
            }

            if (!$(event.target).is(settings.triggerSelector) &&
                !$(event.target).closest(settings.menuSelector).length) {

                $(settings.menuSelector)
                    .removeClass('slideInLeft')
                    .addClass('slideOutLeft');
            }
        });

        return self;
    };
}(jQuery));

(function ($) {
    'use strict';
    var settings;

    $.fn.tuxedoMenu = function (options) {
        var self = this;

        // Extend default settings with options
        settings = $.extend({
            triggerSelector: '.tuxedo-menu-trigger',
            menuSelector: '.tuxedo-menu',
            isFixed: true
        }, options);

        self.addClass('tuxedo-menu tuxedo-menu-pristine animated')
            .toggleClass('tuxedo-menu-visible', !settings.isFixed)
            .toggleClass('tuxedo-menu-fixed slideOutLeft', settings.isFixed);
        $(settings.triggerSelector).addClass('tuxedo-menu-trigger');

        $(settings.triggerSelector).on('click', function () {
            if (!settings.isFixed) {
                return;
            }
            $(settings.menuSelector)
                .toggleClass('slideInLeft slideOutLeft')
                .addClass('tuxedo-menu-visible');
            return false;
        });

        $(document).click(function (event) {
            if (!settings.isFixed ||
                $(event.target).is(settings.triggerSelector)) {
                return;
            }

            if (!$(event.target).is(settings.triggerSelector) &&
                !$(event.target).closest(settings.menuSelector).length) {

                $(settings.menuSelector)
                    .removeClass('slideInLeft')
                    .addClass('slideOutLeft');
            }
        });

        return self;
    };
}(jQuery));

Stop event bubbling when trigger is clicked


module.exports = {
  setupFilesAfterEnv: ['@testing-library/jest-dom/extend-expect'],
  transform: {
    '^.+\\.[jt]sx?$': 'babel-jest',
  },
  transformIgnorePatterns: ['/node_modules/(?!@centreon/ui).+\\.jsx?$'],
  moduleNameMapper: {
    '\\.(s?css|png|svg)$': 'identity-obj-proxy',
  },
  testPathIgnorePatterns: ['/node_modules/'],
};

module.exports = {
  setupFilesAfterEnv: ['@testing-library/jest-dom/extend-expect'],
  transform: {
    '^.+\\.[jt]sx?$': 'babel-jest',
  },
  transformIgnorePatterns: ['/node_modules/(?!@centreon/ui).+\\.jsx?$'],
  moduleNameMapper: {
    '\\.(s?css|png|svg)$': 'identity-obj-proxy',
    '@centreon/ui': '<rootDir>/node_modules/@centreon/centreon-frontend/packages/centreon-ui',
    '@centreon/ui-context': '<rootDir>/node_modules/@centreon/centreon-frontend/packages/ui-context'
  },
  testPathIgnorePatterns: ['/node_modules/'],
};

Add module resolution for jest


require.config({
  paths: {
    text: 'lib/require-text',
    css: 'lib/require-css',

    jquery: 'lib/jquery',

    underscore: 'lib/underscore',
    'underscore.crunch': 'lib/underscore.crunch',

    backbone: 'lib/backbone',

    marked: 'lib/marked',
    'marked.highlight': 'lib/marked.highlight',

    moment: 'lib/moment',

    highlight: 'lib/highlight',

    "disqus.embed": '//livingwithdjango.disqus.com/embed',
    "disqus.count": '//livingwithdjango.disqus.com/count'
  },

  shim: {
    highlight: {
      deps: ['css!style/highlight.css'],
      exports: 'hljs'
    }
  }
});

require(
  [
    'backbone', 'models', 'views', 'css!style/main.css'
  ], function(B, M, V) {
    new (B.Router.extend({
      routes: {'': 'list', '*src': 'entry'},
      list: function() { new V.List(); },
      entry: function(src) { new V.Entry({model: new M.Entry({src: src})}); }
    }));

    // Disqus needs to be required once the "disqus_thread" element is on the page, so we need to
    // reload the page whenever that element is added.  Easier to just always reload the page.
    $('body').on('click', 'a', function() {window.location.reload();});

    B.history.start({root: '/living-with-django/'});
  }
);

require.config({
  paths: {
    text: 'lib/require-text',
    css: 'lib/require-css',

    jquery: 'lib/jquery',

    underscore: 'lib/underscore',
    'underscore.crunch': 'lib/underscore.crunch',

    backbone: 'lib/backbone',

    marked: 'lib/marked',
    'marked.highlight': 'lib/marked.highlight',

    moment: 'lib/moment',

    highlight: 'lib/highlight',

    "disqus.embed": '//livingwithdjango.disqus.com/embed',
    "disqus.count": '//livingwithdjango.disqus.com/count'
  },

  shim: {
    highlight: {
      deps: ['css!style/highlight.css'],
      exports: 'hljs'
    }
  }
});

require(
  [
    'backbone', 'models', 'views', 'css!style/main.css'
  ], function(B, M, V) {
    new (B.Router.extend({
      routes: {'': 'list', '*src': 'entry'},
      list: function() { new V.List(); },
      entry: function(src) { new V.Entry({model: new M.Entry({src: src})}); }
    }));

    // Disqus needs to be required once the "disqus_thread" element is on the page, so we need to
    // reload the page whenever that element is added.  Easier to just always reload the page.
    $('body').on('click', 'a', function(e) {
      e.preventDefault();
      window.location.replace($(this).attr('href'));
      window.location.reload();
    });

    B.history.start({root: '/living-with-django/'});
  }
);

Improve disqus page reload hack.


/*
Language: Go
Author: Stephan Kountso aka StepLg <steplg@gmail.com>
Contributors: Evgeny Stepanischev <imbolk@gmail.com>
Description: Google go language (golang). For info about language see http://golang.org/
Category: system
*/

function(hljs) {
  var GO_KEYWORDS = {
    keyword:
      'break default func interface select case map struct chan else goto package switch ' +
      'const fallthrough if range type continue for import return var go defer ' +
      'bool byte complex64 complex128 float32 float64 int8 int16 int32 int64 string uint8 ' +
      'uint16 uint32 uint64 int uint uintptr rune',
    literal:
       'true false iota nil',
    built_in:
      'append cap close complex copy imag len make new panic print println real recover delete'
  };
  return {
    aliases: ['golang'],
    keywords: GO_KEYWORDS,
    illegal: '</',
    contains: [
      hljs.C_LINE_COMMENT_MODE,
      hljs.C_BLOCK_COMMENT_MODE,
      hljs.QUOTE_STRING_MODE,
      {
        className: 'string',
        begin: '\'', end: '[^\\\\]\''
      },
      {
        className: 'string',
        begin: '`', end: '`'
      },
      {
        className: 'number',
        variants: [
          {begin: hljs.C_NUMBER_RE + '[dflsi]', relevance: 1},
          hljs.C_NUMBER_MODE
        ]
      },
      {
        begin: /:=/ // relevance booster
      }
    ]
  };
}

/*
Language: Go
Author: Stephan Kountso aka StepLg <steplg@gmail.com>
Contributors: Evgeny Stepanischev <imbolk@gmail.com>
Description: Google go language (golang). For info about language see http://golang.org/
Category: system
*/

function(hljs) {
  var GO_KEYWORDS = {
    keyword:
      'break default func interface select case map struct chan else goto package switch ' +
      'const fallthrough if range type continue for import return var go defer ' +
      'bool byte complex64 complex128 float32 float64 int8 int16 int32 int64 string uint8 ' +
      'uint16 uint32 uint64 int uint uintptr rune',
    literal:
       'true false iota nil',
    built_in:
      'append cap close complex copy imag len make new panic print println real recover delete'
  };
  return {
    aliases: ['golang'],
    keywords: GO_KEYWORDS,
    illegal: '</',
    contains: [
      hljs.C_LINE_COMMENT_MODE,
      hljs.C_BLOCK_COMMENT_MODE,
      {
        className: 'string',
        variants: [
          hljs.QUOTE_STRING_MODE,
          {begin: '\'', end: '[^\\\\]\''},
          {begin: '`', end: '`'},
        ]
      },
      {
        className: 'number',
        variants: [
          {begin: hljs.C_NUMBER_RE + '[dflsi]', relevance: 1},
          hljs.C_NUMBER_MODE
        ]
      },
      {
        begin: /:=/ // relevance booster
      }
    ]
  };
}

Unify strings in Go with variants


module.exports = {
  syntax: "postcss-scss",
  plugins: {
    stylelint: {},
    "postcss-import": { addModulesDirectories: ["src"] },
    "postcss-cssnext": {
      // This prints a warning when used with cssnano as both include
      // autoprefixer as dependencies
      warnForDuplicates: false,
      features: {
        // Preserves CSS variables
        // When this is set true, the variables are resolved at build-time
        customProperties: false
      }
    },
    precss: {},
    cssnano: { discardComments: { removeAll: true } },
    "postcss-reporter": {}
  }
};

module.exports = {
  syntax: "postcss-scss",
  plugins: {
    "postcss-import": { addModulesDirectories: ["src"] },
    "postcss-cssnext": {
      // This prints a warning when used with cssnano as both include
      // autoprefixer as dependencies
      warnForDuplicates: false,
      features: {
        // Preserves CSS variables
        // When this is set true, the variables are resolved at build-time
        customProperties: false
      }
    },
    precss: {},
    cssnano: {},
    "postcss-reporter": {}
  }
};

Remove stylelint from postcss chain, reset cssnano to defaults


import axios from 'axios';

export function getRestaurants ({ commit }) {
  return new Promise((resolve, reject) => {
    axios
      .get('/api/restaurant')
      .then((response) => {
        commit('updateRestaurants', response.data.restaurants);
        resolve(response);
      })
      .catch((err) => {
        reject(err);
      });
  });
}

export function getRestaurant ({ commit }, identifier) {
  return new Promise((resolve, reject) => {
    axios
      .get('/api/restaurant/' + identifier)
      .then((response) => {
        resolve(response);
      })
      .catch((err) => {
        reject(err);
      });
  });
}

export function setRegion ({ commit }, value) {
  commit('updateRegion', value);
}

export function setShowMapList ({ commit }, value) {
  commit('updateShowMapList', value);
}

// expects payload to be {'restaurant': name, 'favourite': state}
export function setFavourite ({ commit }, payload) {
  commit('updateFavourite', payload);
}

export function updateVisRes ({ commit }) {
  commit('updateVisRes');
}

import axios from 'axios';

export function getRestaurants ({ commit }) {
  return new Promise((resolve, reject) => {
    axios
      .get('/api/restaurant')
      .then((response) => {
        commit('updateRestaurants', response.data.restaurants);
        commit('updateVisRes', response.data.restaurants);
        resolve(response);
      })
      .catch((err) => {
        reject(err);
      });
  });
}

export function getRestaurant ({ commit }, identifier) {
  return new Promise((resolve, reject) => {
    axios
      .get('/api/restaurant/' + identifier)
      .then((response) => {
        resolve(response);
      })
      .catch((err) => {
        reject(err);
      });
  });
}

export function setRegion ({ commit }, value) {
  commit('updateRegion', value);
}

export function setShowMapList ({ commit }, value) {
  commit('updateShowMapList', value);
}

// expects payload to be {'restaurant': name, 'favourite': state}
export function setFavourite ({ commit }, payload) {
  commit('updateFavourite', payload);
}

export function updateVisRes ({ commit }) {
  commit('updateVisRes');
}

Update visible restaurants after updating restaurants


import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Route } from 'react-router-dom';

import SchedulerClient from 'client/scheduler-client';
import Navigation from 'components/Navigation';
import Home from 'pages/Home';
import Instance from 'pages/Instance';
import Job from 'pages/Job';
import Jobs from 'pages/Jobs';
import Update from 'pages/Update';
import Updates from 'pages/Updates';

import 'bootstrap/dist/css/bootstrap.css';
import '../resources/source-sans-pro.css'
import '../sass/app.scss';

const injectApi = (Page) => (props) => <Page api={SchedulerClient} {...props} />;

const SchedulerUI = () => (
  <Router>
    <div>
      <Navigation />
      <Route component={injectApi(Home)} exact path='/beta/scheduler' />
      <Route component={injectApi(Jobs)} exact path='/beta/scheduler/:role' />
      <Route component={injectApi(Jobs)} exact path='/beta/scheduler/:role/:environment' />
      <Route component={injectApi(Job)} exact path='/beta/scheduler/:role/:environment/:name' />
      <Route
        component={injectApi(Instance)}
        exact
        path='/beta/scheduler/:role/:environment/:name/:instance' />
      <Route
        component={injectApi(Update)}
        exact
        path='/beta/scheduler/:role/:environment/:name/update/:uid' />
      <Route component={injectApi(Updates)} exact path='/beta/updates' />
    </div>
  </Router>
);

ReactDOM.render(<SchedulerUI />, document.getElementById('root'));

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Route } from 'react-router-dom';

import SchedulerClient from 'client/scheduler-client';
import Navigation from 'components/Navigation';
import Home from 'pages/Home';
import Instance from 'pages/Instance';
import Job from 'pages/Job';
import Jobs from 'pages/Jobs';
import Update from 'pages/Update';
import Updates from 'pages/Updates';

import 'bootstrap/dist/css/bootstrap.css';
import '../resources/source-sans-pro.css';
import '../sass/app.scss';

const injectApi = (Page) => (props) => <Page api={SchedulerClient} {...props} />;

const SchedulerUI = () => (
  <Router>
    <div>
      <Navigation />
      <Route component={injectApi(Home)} exact path='/beta/scheduler' />
      <Route component={injectApi(Jobs)} exact path='/beta/scheduler/:role' />
      <Route component={injectApi(Jobs)} exact path='/beta/scheduler/:role/:environment' />
      <Route component={injectApi(Job)} exact path='/beta/scheduler/:role/:environment/:name' />
      <Route
        component={injectApi(Instance)}
        exact
        path='/beta/scheduler/:role/:environment/:name/:instance' />
      <Route
        component={injectApi(Update)}
        exact
        path='/beta/scheduler/:role/:environment/:name/update/:uid' />
      <Route component={injectApi(Updates)} exact path='/beta/updates' />
    </div>
  </Router>
);

ReactDOM.render(<SchedulerUI />, document.getElementById('root'));

Fix lint build error from Fonts patch.


'use babel';

describe('rustsym', () => {

  beforeEach(() => {
    waitsForPromise(() => atom.packages.activatePackage('rustsym'));
  });

  it('should be activated', () => {
    // TODO: Package depends on activation commands now
    expect(true);
  });

});

'use babel';

describe('rustsym', () => {

  beforeEach(() => waitsForPromise(() => atom.packages.activatePackage('rustsym')));

  describe('given a Rust source file is open', () => {

    beforeEach(() => waitsForPromise(() => atom.workspace.open('tmp.rs')));

    describe('when the manual file symbols command is used', () => {
      it('should show the file symbols search view', () => {
        let workspaceElement = atom.views.getView(atom.workspace);
        let textEditorElement = atom.views.getView(atom.workspace.getActiveTextEditor());
        jasmine.attachToDOM(textEditorElement);
        atom.commands.dispatch(textEditorElement, 'rustsym:toggle-file-symbols');
        expect(workspaceElement.querySelector('.rustsym')).toExist();
        let statusBarModeElement = workspaceElement.querySelector('.rustsym-status-bar__mode');
        expect(statusBarModeElement).toExist();
        expect(statusBarModeElement.innerText.indexOf('file')).not.toBe(-1, 'incorrect search mode');
      });
    });

    describe('when the manual project symbols command is used', () => {
      it('should show the project symbols search view', () => {
        let workspaceElement = atom.views.getView(atom.workspace);
        jasmine.attachToDOM(workspaceElement);
        atom.commands.dispatch(workspaceElement, 'rustsym:toggle-project-symbols');
        expect(workspaceElement.querySelector('.rustsym')).toExist();
        let statusBarModeElement = workspaceElement.querySelector('.rustsym-status-bar__mode');
        expect(statusBarModeElement).toExist();
        expect(statusBarModeElement.innerText.indexOf('project')).not.toBe(-1, 'incorrect search mode');
      });
    });

  });

});

Add basic tests for revised activation


'use strict';

var memoize        = require('memoizee/plain')
  , validDb        = require('dbjs/valid-dbjs')
  , defineFile     = require('dbjs-ext/object/file')
  , defineJpegFile = require('dbjs-ext/object/file/image-file/jpeg-file');

module.exports = memoize(function (db) {
	var File, JpegFile;
	validDb(db);
	File               = defineFile(db);
	File.prototype.url = function () {
		return this.path ? '/' + encodeURIComponent(this.path) : null;
	};
	JpegFile = defineJpegFile(db);
	File.prototype.defineProperties({
		preview: { type: File, value: function () {
			return this.isPreviewGenerated ? this.generatedPreview : this;
		} },
		isPreviewGenerated: { type: db.Boolean, value: true },
		generatedPreview: { type: File, nested: true },
		thumb: { type: JpegFile, nested: true }
	});
	File.accept = ['image/jpeg', 'application/pdf', 'image/png'];

	return File;
}, { normalizer: require('memoizee/normalizers/get-1')() });

'use strict';

var memoize        = require('memoizee/plain')
  , validDb        = require('dbjs/valid-dbjs')
  , defineFile     = require('dbjs-ext/object/file')
  , defineJpegFile = require('dbjs-ext/object/file/image-file/jpeg-file');

module.exports = memoize(function (db) {
	var File, JpegFile;
	validDb(db);
	File               = defineFile(db);
	File.prototype.url = function () {
		return this.path ? '/' + encodeURIComponent(this.path) : null;
	};
	JpegFile = defineJpegFile(db);
	File.prototype.defineProperties({
		preview: { type: File, value: function () {
			return this.isPreviewGenerated ? this.generatedPreview : this;
		} },
		isPreviewGenerated: { type: db.Boolean, value: true },
		generatedPreview: { type: File, nested: true },
		thumb: { type: JpegFile, nested: true }
	});
	File.accept = ['image/jpeg', 'application/pdf', 'image/png', 'image/pjpeg', 'image/x-png'];

	return File;
}, { normalizer: require('memoizee/normalizers/get-1')() });

Support old microsoft specific mime types


import babel from 'rollup-plugin-babel';

export default {
  entry: 'index.js',
  moduleName: 'fcPath',
  format: 'umd',
  plugins: [ babel() ],
  dest: 'build/d3fc-path.js',
  globals: {
    d3: 'd3'
  }
};

import babel from 'rollup-plugin-babel';

export default {
  entry: 'index.js',
  moduleName: 'fc_path',
  format: 'umd',
  plugins: [ babel() ],
  dest: 'build/d3fc-path.js',
  globals: {
    d3: 'd3'
  }
};

Rename exported UMD module to fc_path


// XXX this file no longer makes sense in isolation.  take it apart as
// part file reorg on the 'ui' package
var globalHelpers = {};

UI.registerHelper = function (name, func) {
  globalHelpers[name] = func;
};

UI._globalHelper = function (name) {
  return globalHelpers[name];
};

// Utility to HTML-escape a string.
UI._escape  = (function() {
  var escape_map = {
    "<": "<",
    ">": ">",
    '"': """,
    "'": "'",
    "`": "`", /* IE allows backtick-delimited attributes?? */
    "&": "&"
  };
  var escape_one = function(c) {
    return escape_map[c];
  };

  return function (x) {
    return x.replace(/[&<>"'`]/g, escape_one);
  };
})();

// Return these from {{...}} helpers to achieve the same as returning
// strings from {{{...}}} helpers
Handlebars.SafeString = function(string) {
  this.string = string;
};
Handlebars.SafeString.prototype.toString = function() {
  return this.string.toString();
};

// XXX COMPAT WITH 0.7.2
Handlebars = {};
Handlebars._escape = UI._escape;
Handlebars.registerHelper = UI.registerHelper;

// XXX this file no longer makes sense in isolation.  take it apart as
// part file reorg on the 'ui' package
var globalHelpers = {};

UI.registerHelper = function (name, func) {
  globalHelpers[name] = func;
};

UI._globalHelper = function (name) {
  return globalHelpers[name];
};

Handlebars = {};
Handlebars.registerHelper = UI.registerHelper;

// Utility to HTML-escape a string.
UI._escape = Handlebars._escape = (function() {
  var escape_map = {
    "<": "<",
    ">": ">",
    '"': """,
    "'": "'",
    "`": "`", /* IE allows backtick-delimited attributes?? */
    "&": "&"
  };
  var escape_one = function(c) {
    return escape_map[c];
  };

  return function (x) {
    return x.replace(/[&<>"'`]/g, escape_one);
  };
})();

// Return these from {{...}} helpers to achieve the same as returning
// strings from {{{...}}} helpers
Handlebars.SafeString = function(string) {
  this.string = string;
};
Handlebars.SafeString.prototype.toString = function() {
  return this.string.toString();
};

Revert "Mark backcompat on some Handlebars functions"


'use babel'

import { Emitter } from 'atom'

export default class DebbugerStub {

  constructor() {
    this.emitter = new Emitter
  }

  /* Interface */
  name() {
    return 'DebuggerStub'
  }

  start(target, breakpoints) {

  }

  onSessionEvent(callback) {
    return this.emitter.on('session', callback)
  }

  onBreakpointEvent(callback) {
    return this.emitter.on('breakpoint', callback)
  }

  /* For tests */
  emitSessionEvent(notification) {
    this.emitter.emit('session', notification)
  }

  emitBreakpointEvent(notification) {
    this.emitter.emit('breakpoint', notification)
  }
}

'use babel'

import { Emitter } from 'atom'

export default class DebbugerStub {

  constructor() {
    this.emitter = new Emitter
  }

  /* Interface */
  name() {
    return 'DebuggerStub'
  }

  start(target, breakpoints) {

  }

  onSessionEvent(callback) {
    return this.emitter.on('session', callback)
  }

  onBreakpointEvent(callback) {
    return this.emitter.on('breakpoint', callback)
  }

  onTargetEvent(callback) {
    return this.emitter.on('target', callback)
  }

  /* For tests */
  emitSessionEvent(notification) {
    this.emitter.emit('session', notification)
  }

  emitBreakpointEvent(notification) {
    this.emitter.emit('breakpoint', notification)
  }
}

Add onTargetEvent to test debugger stub.