// If you setup basic auth in node-sonos-http-api's settings.json, change the username
// and password here.  Otherwise, just leave this alone and it will work without auth.
var auth = new Buffer("YOUR_USERNAME" + ":" + "YOUR_PASSWORD").toString("base64");

var options = {
  appid: "ENTER_YOUR_APP_ID_FOR_ECHO_HERE",
  host: "host_for_sonos_api",
  port: "5005",
  headers: {
      'Authorization': 'Basic ' + auth,
      'Content-Type': 'application/json'
  },
  useHttps: false, // Change to true if you setup node-sonos-http-api with HTTPS
  rejectUnauthorized: true, // Change to false if you self-signed your certificate
  defaultRoom: '',				        // Allows you to specify a default room when one is not specified in the utterance
  defaultMusicService: 'presets', // Supports presets, apple, spotify, deezer, or library
  advancedMode: false,             // Allows you to specify and change default rooms and music services. Requires additional AWS setup
  useSQS: false   // Use AWS SQS and node-sqs-proxy for secure communications
};

module.exports = options;

// If you setup basic auth in node-sonos-http-api's settings.json, change the username
// and password here.  Otherwise, just leave this alone and it will work without auth.
var auth = new Buffer(process.env.AUTH_USERNAME + ":" + process.env.AUTH_PASSWORD).toString("base64");

var options = {
  appid: process.env.APPID,
  host: process.env.HOST,
  port: process.env.PORT || '5005',
  headers: {
      'Authorization': 'Basic ' + auth,
      'Content-Type': 'application/json'
  },
  useHttps: process.env.USE_HTTPS || false, // Change to true if you setup node-sonos-http-api with HTTPS
  rejectUnauthorized: process.env.REJECT_UNAUTHORIZED || true, // Change to false if you self-signed your certificate
  defaultRoom: process.env.DEFAULT_ROOM || '',				        // Allows you to specify a default room when one is not specified in the utterance
  defaultMusicService: process.env.DEFAULT_MUSIC_SERVICE || 'presets', // Supports presets, apple, spotify, deezer, or library
  advancedMode: process.env.ADVANCED_MODE || false,             // Allows you to specify and change default rooms and music services. Requires additional AWS setup
  useSQS: process.env.USE_SQS || false   // Use AWS SQS and node-sqs-proxy for secure communications
};

module.exports = options;

Allow options to be set with environment variables in lambda


module.exports = {
  getRequest: (url, callback) => {
    var request = new XMLHttpRequest();
    request.open('GET', url, true);
    request.onload = () => {
      if (request.status >= 200 && request.status < 400) {
        var data = JSON.parse(request.responseText);
        callback(data);
      } else {
        console.error(url, request.responseText);
      }
    };
    request.onerror = () => {
      console.error(url);
    };
    request.send();
  },

  postJSONRequest: (url, data, callback) => {
    var request = new XMLHttpRequest();
    request.open('POST', url, true);
    request.setRequestHeader('Content-Type',
                             'application/json; charset=UTF-8');
    request.onload = () => {
      if (request.status >= 200 && request.status < 400) {
        var data = JSON.parse(request.responseText);
        callback(data);
      } else {
        console.error(url, request.responseText);
      }
    };
    request.onerror = () => {
      console.error(url);
    };
    request.send(JSON.stringify(data));
  }
};

module.exports = {
  getRequest: (url, callback) => {
    let request = new XMLHttpRequest();
    request.open('GET', url, true);
    request.onload = () => {
      if (request.status >= 200 && request.status < 400) {
        const data = JSON.parse(request.responseText);
        callback(data);
      } else {
        console.error(url, request.responseText);
      }
    };
    request.onerror = () => {
      console.error(url);
    };
    request.send();
  },

  postJSONRequest: (url, data, callback) => {
    let request = new XMLHttpRequest();
    request.open('POST', url, true);
    request.setRequestHeader('Content-Type',
                             'application/json; charset=UTF-8');
    request.onload = () => {
      if (request.status >= 200 && request.status < 400) {
        const data = JSON.parse(request.responseText);
        callback(data);
      } else {
        console.error(url, request.responseText);
      }
    };
    request.onerror = () => {
      console.error(url);
    };
    request.send(JSON.stringify(data));
  }
};

Use let and const instead of var


/* eslint-env node */
module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        shippedProposals: true,
        useBuiltIns: 'usage',
        corejs: '3',
        targets: ['last 1 Chrome versions', 'last 1 Firefox versions', 'last 1 Safari versions'],
      },
    ],
  ],
  plugins: [
    [
      '@babel/plugin-proposal-decorators',
      {
        legacy: true,
      },
    ],
    ['@babel/plugin-proposal-class-properties', { loose: true }],
    '@babel/plugin-syntax-dynamic-import',
    ['@babel/plugin-proposal-object-rest-spread', { loose: true, useBuiltIns: true }],
    'babel-plugin-macros',
    ['emotion', { sourceMap: true, autoLabel: true }],
  ],
};

/* eslint-env node */

// Inject the named blocks polyfill into the template compiler (and then into the babel plugin)
const templateCompiler = require('ember-source/dist/ember-template-compiler');
const namedBlocksPolyfillPlugin = require('ember-named-blocks-polyfill/lib/named-blocks-polyfill-plugin');

templateCompiler.registerPlugin('ast', namedBlocksPolyfillPlugin);

module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        shippedProposals: true,
        useBuiltIns: 'usage',
        corejs: '3',
        targets: ['last 1 Chrome versions', 'last 1 Firefox versions', 'last 1 Safari versions'],
      },
    ],
  ],
  plugins: [
    [
      '@babel/plugin-proposal-decorators',
      {
        legacy: true,
      },
    ],
    ['@babel/plugin-proposal-class-properties', { loose: true }],
    '@babel/plugin-syntax-dynamic-import',
    ['@babel/plugin-proposal-object-rest-spread', { loose: true, useBuiltIns: true }],
    'babel-plugin-macros',
    ['emotion', { sourceMap: true, autoLabel: true }],
    [
      'babel-plugin-htmlbars-inline-precompile',
      {
        precompile: templateCompiler.precompile,
        modules: {
          'ember-cli-htmlbars': 'hbs',
          'ember-cli-htmlbars-inline-precompile': 'default',
          'htmlbars-inline-precompile': 'default',
        },
      },
      // This is an arbitrary label to prevent a collision with the existing htmlbars inline precompile
      // plugin that comes in from the @storybook/ember defaults.
      // TODO: After upgrading to Storybook 6.1 this should move into the new emberOptions construct.
      'override',
    ],
  ],
};

Include the named-blocks polyfill compiler in the storybook babel options


import React from "react";
import { connect } from "react-redux";
import styled from "styled-components";
import { pushState } from "../../app/actions";
import { Icon } from "../../base";
import Install from "./Install";
import ReleasesList from "./List";

const StyledReleases = styled.div`
    flex: 1 0 auto;
    margin-right: 15px;
`;

export const Releases = ({ onShowInstall, releases }) => {
    if (releases.length) {
        return (

        );
    }

    return (

    );
};

export const mapStateToProps = state => ({
    releases: state.updates.releases
});

export const mapDispatchToProps = dispatch => ({
    onShowInstall: () => {
        dispatch(pushState({ install: true }));
    }
});

export default connect(mapStateToProps, mapDispatchToProps)(Releases);

import React from "react";
import { connect } from "react-redux";
import styled from "styled-components";
import { pushState } from "../../app/actions";
import { Box, Icon } from "../../base";
import Install from "./Install";
import ReleasesList from "./List";

const StyledReleases = styled(Box)`
    flex: 1 0 auto;
    margin-right: 15px;
`;

export const Releases = ({ onShowInstall, releases }) => {
    if (releases.length) {
        return (

        );
    }

    return (

    );
};

export const mapStateToProps = state => ({
    releases: state.updates.releases
});

export const mapDispatchToProps = dispatch => ({
    onShowInstall: () => {
        dispatch(pushState({ install: true }));
    }
});

export default connect(mapStateToProps, mapDispatchToProps)(Releases);

Put Box around 'Software is up-to-date'


var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');

var bodyParser = require('body-parser');var express = require('express');
var router = express.Router();

var mongoose = require('mongoose');
var jwt = require('jsonwebtoken');
var config = require('../config.js');
var User = require('../models/user.js');

router.use(function(req, res, next) {
    var token = req.body.token || req.query.token || req.headers['x-access-token'];

    if(token) {
        jwt.verify(token, 'supersecret', function(err, decoded) {
            if(err) {
                return res.json({
                    success: false,
                    message: 'Failed to authenticate'
                });
            } else {
                req.decoded = decoded;
                next();
            }
        });
    } else {
        return res.status(403).send({
                success: false,
                message: 'No token provided'
        });
    }
});

/* GET users listing. */
router.get('/', function(req, res, next) {
    User.find({}, function(err, users) {
        res.json(users);
    });
});

module.exports = router;

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');

var bodyParser = require('body-parser');
var express = require('express');
var router = express.Router();

var mongoose = require('mongoose');
var jwt = require('jsonwebtoken');
var config = require('../config.js');
var User = require('../models/user.js');

router.use(function(req, res, next) {
    var token = req.body.token || req.query.token || req.headers['x-access-token'];

    if(token) {
        jwt.verify(token, 'supersecret', function(err, decoded) {
            if(err) {
                return res.json({
                    success: false,
                    message: 'Failed to authenticate'
                });
            } else {
                req.decoded = decoded;
                next();
            }
        });
    } else {
        return res.status(403).send({
                success: false,
                message: 'No token provided'
        });
    }
});

/* GET users listing. */
router.get('/', function(req, res, next) {
    User.find({}, function(err, users) {
        res.json(users);
    });
});

module.exports = router;

Move statement to 2 lines


/* global window */
export default function(Handlebars) {
  /* istanbul ignore next */
  let root = typeof global !== 'undefined' ? global : window,
      $Handlebars = root.Handlebars;
  /* istanbul ignore next */
  Handlebars.noConflict = function() {
    if (root.Handlebars === Handlebars) {
      root.Handlebars = $Handlebars;
    }
  };
}

/* global window */
export default function(Handlebars) {
  /* istanbul ignore next */
  let root = typeof global !== 'undefined' ? global : window,
      $Handlebars = root.Handlebars;
  /* istanbul ignore next */
  Handlebars.noConflict = function() {
    if (root.Handlebars === Handlebars) {
      root.Handlebars = $Handlebars;
    }
    return Handlebars;
  };
}

Return current handlebars instance from noConflict


const config = require('../../../knexfile').web
const knex = require('knex')(config)

module.exports = function (id, fromDate, toDate) {
  return knex('workload_points_calculations')
        .join('workload', 'workload_points_calculations.workload_id', '=', 'workload.id')
        .join('workload_report', 'workload_points_calculations.workload_report_id', '=', 'workload_report.id')
        .where('workload_report.effective_from', '>=', fromDate)
        .where('workload_report.effective_from', '<=', toDate)
        .where('workload.workload_owner_id', id)
        .select('workload_report.effective_from',
                'workload_points_calculations.total_points',
                'workload_points_calculations.sdr_points',
                'workload_points_calculations.sdr_conversion_points',
                'workload_points_calculations.paroms_points',
                'workload_points_calculations.available_points',
                'workload_points_calculations.reduction_hours')
       .then(function (workloadReports) {
         return workloadReports
       })
}

const config = require('../../../knexfile').web
const knex = require('knex')(config)

module.exports = function (id, fromDate, toDate) {
  return knex('workload_points_calculations')
    .join('workload', 'workload_points_calculations.workload_id', '=', 'workload.id')
    .join('workload_report', 'workload_points_calculations.workload_report_id', '=', 'workload_report.id')
    .where('workload_report.effective_from', '>=', fromDate)
    .where('workload_report.effective_from', '<=', toDate)
    .where('workload.workload_owner_id', id)
    .select('workload_report.effective_from',
            'workload_points_calculations.total_points',
            'workload_points_calculations.sdr_points',
            'workload_points_calculations.sdr_conversion_points',
            'workload_points_calculations.paroms_points',
            'workload_points_calculations.available_points',
            'workload_points_calculations.reduction_hours')
    .orderBy('workload_report.effective_from')
    .then(function (workloadReports) {
      return workloadReports
    })
}

Add order by to individual capacity query


"use strict";

const build = require('@glimmer/build');

module.exports = function() {
  return build();
}

"use strict";

const build = require('@glimmer/build');

module.exports = function() {
  return build({
    external: [
      'broccoli-config-loader',
      'broccoli-config-replace',
      'broccoli-funnel',
      'broccoli-concat',
      'path',
      'fs',
      'lodash.defaultsdeep',
      'broccoli-typescript-compiler',
      'exists-sync',
      'broccoli-merge-trees',
      'broccoli-sass',
      'broccoli-asset-rev',
      'broccoli-uglify-sourcemap',
      '@glimmer/resolution-map-builder',
      '@glimmer/resolver-configuration-builder',
      'broccoli-rollup',
      'rollup-plugin-node-resolve',
      'rollup-plugin-babel',
      'broccoli-persistent-filter',
      '@glimmer/compiler',
      'broccoli-source',
      'heimdalljs-logger',
      'broccoli-stew'
    ]
  });
}

Clear warnings for externals with Rollup.


'use strict';
var express = require('express');
var co = require('collections-online');

// This allows loading of environment variables from a .env file
require('dotenv').config({silent: true});
// Loading the configuration
var config = require('./config');

// Creating an express app
var app = express();

// Set up Keystone
var keystone = require('keystone');

keystone.init({
  'name': 'KBH-billeder',

  'static': ['generated'],
  'views': 'app/views',
  'view engine': 'jade',

  'auto update': true,
  'mongo': 'mongodb://localhost/kbh-billeder',

  'session': true,
  'auth': true,
  'user model': 'User',
  'cookie secret': '1234'
});

keystone.import('./models');

keystone.set('routes', require('./routes'));

keystone.set('nav', {
	users: 'users',
});

keystone.mount('/content', app, function() {
});

// Asking collections online to set-up itself
co.initialize(app, config);

'use strict';
var express = require('express');
var co = require('collections-online');

// This allows loading of environment variables from a .env file
require('dotenv').config({silent: true});
// Loading the configuration
var config = require('./config');

// Creating an express app
var app = express();

// Set up Keystone
var keystone = require('keystone');

keystone.init({
  'name': 'KBH-billeder',

  'static': ['generated'],
  'views': 'app/views',
  'view engine': 'jade',

  'auto update': true,
  'mongo': 'mongodb://localhost/kbh-billeder',

  'session': true,
  'auth': true,
  'user model': 'User',
  'cookie secret': '1234'
});

keystone.import('./models');

keystone.set('routes', require('./routes'));

keystone.set('nav', {
	users: 'users',
	pages: 'pages',
});

keystone.mount('/content', app, function() {
});

// Asking collections online to set-up itself
co.initialize(app, config);

Add pages to admin UI menu


var express = require('express');
var xml = require('xml');
var app = express();
var suncalc = require('suncalc');
var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/sunrisedb');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error...'));
db.once('open', function callback() {
    console.log('multivision db opened');
});

app.get('/xml', function(req, res) {
    var xmlresult = {
    APe: "35", Mandis: "32"
    };
    res.set('Content-Type', 'text/xml');
    res.send(xml(xmlresult));
});

// Sample call: http://localhost:3000/?lat=59.2&lon=17.4&date=2016-01-14
app.get('*', function(req, res) {
    var lat = req.query.lat;
    var lon = req.query.lon;
    var date = new Date(req.query.date);
    var times = suncalc.getTimes(date, lat, lon);
    res.json(times);
});

var port = 3000;
app.listen(port);
console.log('Listen on port: ' + port + '...');

var express = require('express');
var xml = require('xml');
var app = express();
var suncalc = require('suncalc');
var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/sunrisedb');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error...'));
db.once('open', function callback() {
    console.log('multivision db opened');
});

// Sample call: http://localhost:3000/?lat=59.2&lon=17.4&date=2016-01-14
app.get('*', function(req, res) {
    var lat = req.query.lat;
    var lon = req.query.lon;
    var date = new Date(req.query.date);
    var times = suncalc.getTimes(date, lat, lon);
    res.json(times);
});

var port = 3000;
app.listen(port);
console.log('Listen on port: ' + port + '...');

Clean of sample xml result


import { expect } from 'chai';
import { describe, it } from 'mocha';
import { setupTest } from 'ember-mocha';

describe('Unit | Route | visualize/graph', function() {
  setupTest('route:visualize/graph', {
    needs: [
      'service:metrics',
      'ember-metrics@metrics-adapter:piwik'
    ]
  });

  it('exists', function() {
    let route = this.subject();
    expect(route).to.be.ok;
  });
});

import { expect } from 'chai';
import { describe, it } from 'mocha';
import { setupTest } from 'ember-mocha';

describe('Unit | Route | visualize/graph', function() {
  setupTest('route:visualize/graph', {
    needs: [
      'service:intl',
      'service:metrics',
      'ember-metrics@metrics-adapter:piwik'
    ]
  });

  it('exists', function() {
    let route = this.subject();
    expect(route).to.be.ok;
  });
});

Fix frontend test by adding a mising injection


import React from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
import styles from './input-group.scss';

function InputGroup({className, children, addon, id, ...props}) {
    props.className = cx(styles['input-group'], className);

    return (

            {addon}
            {children}

    );
}

InputGroup.propTypes = {
    children: PropTypes.node,
    className: PropTypes.string,
    addon: PropTypes.node,
    id: PropTypes.string
};

export default InputGroup;

import React from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
import styles from './input-group.scss';

function InputGroup({className, children, addon, addonPosition, id, ...props}) {
    props.className = cx(styles['input-group'], className);

    if (addonPosition === undefined || addonPosition === 'left') {
        return (

                {addon}
                {children}

        );
    } else if (addonPosition === 'right') {
        return (

                {children}
                {addon}

        );
    }
}

const ADDON_POSITIONS = [
    'left',
    'right'
];

InputGroup.propTypes = {
    children: PropTypes.node,
    className: PropTypes.string,
    addon: PropTypes.node,
    addonPosition: PropTypes.oneOf(ADDON_POSITIONS),
    id: PropTypes.string
};

export default InputGroup;

Allow defining addon position for InputGroups


'use strict'; // jshint node: true, browser: false, esnext: true
var proxy   = require('http-proxy').createProxyServer({});
var express = require('express');
var app     = express();

// Configure options

app.use(require('morgan')('dev'));

// Configure routes

app.use('/printsmart/app', express.static(__dirname + '/app'));
app.all('/api/*',          function(req, res) { proxy.web(req, res, { target: 'https://api.cbd.int:443', secure: false } ); } );
app.get('/printsmart*',    function(req, res) { res.sendFile(__dirname + '/app/template.html', {maxAge:300000}); });
app.all('/*',              function(req, res) { res.status(404).send(); });

// LOG PROXY ERROR & RETURN http:500

proxy.on('error', function (e) {
    console.error('proxy error:', e);
});

// START HTTP SERVER

app.listen(process.env.PORT || 2000, '0.0.0.0', function () {
	console.log('Server listening on %j', this.address());
});

process.on('SIGTERM', ()=>process.exit());

'use strict'; // jshint node: true, browser: false, esnext: true
var proxy   = require('http-proxy').createProxyServer({});
var express = require('express');
var app     = express();

// Configure options

app.use(require('morgan')('dev'));

// Configure routes

app.use('/printsmart/app', express.static(__dirname + '/app'));
app.all('/api/*',          function(req, res) { proxy.web(req, res, { target: 'https://api.cbd.int:443', secure: false } ); } );
app.get('/printsmart*',    function(req, res) { res.sendFile(__dirname + '/app/template.html', {maxAge:300000}); });
app.all('/*',              function(req, res) { res.status(404).send(); });

// START HTTP SERVER

app.listen(process.env.PORT || 2000, '0.0.0.0', function () {
	console.log('Server listening on %j', this.address());
});

// Handle proxy errors ignore

proxy.on('error', function (e,req, res) {
    console.error('proxy error:', e);
    res.status(502).send();
});

process.on('SIGTERM', ()=>process.exit());

Send response on proxy timeout


events = {};

events.beforeInsert = function() {
  // Find a class on which the behavior had been set.
  var behaviorData = Astro.utils.findBehavior(this.constructor, 'timestamp');

  // If "hasCreatedField" option is set.
  if (behaviorData.hasCreatedField) {
    // Set value for created field.
    this.set(behaviorData.createdFieldName, new Date());
  }
};

events.beforeUpdate = function() {
  // Find a class on which the behavior had been set.
  var behaviorData = Astro.utils.findBehavior(this.constructor, 'timestamp');

  // If "hasUpdatedField" option is set.
  if (behaviorData.hasUpdatedField) {
    // Set value for updated field.
    this.set(behaviorData.updatedFieldName, new Date());
  }
};

events = {};

events.beforeInsert = function() {
  // Find a class on which the behavior had been set.
  var behaviorData = Astro.utils.findBehavior(this.constructor, 'timestamp');

  // If the "hasCreatedField" option is set.
  if (behaviorData.hasCreatedField) {
    // Set value for created field.
    this.set(behaviorData.createdFieldName, new Date());
  }
};

events.beforeUpdate = function() {
  // Find a class on which the behavior had been set.
  var behaviorData = Astro.utils.findBehavior(this.constructor, 'timestamp');

  // If the "hasUpdatedField" option is set.
  if (behaviorData.hasUpdatedField) {
    // We only set the "updatedAt" field if there are any changes.
    if (_.size(this.getModified())) {
      // Set value for the "updatedAt" field.
      this.set(behaviorData.updatedFieldName, new Date());
    }
  }
};

Set updatedAt field only on fields modification


class ClassWithStaticMethod {

  static staticProperty = "someValue";
  static staticMethod() {
    return 'static method has been called.';
  }

}

console.log(ClassWithStaticMethod.staticProperty);
// output: "someValue"
console.log(ClassWithStaticMethod.staticMethod());
// output: "static method has been called."

class ClassWithStaticMethod {

  static staticProperty = 'someValue';
  static staticMethod() {
    return 'static method has been called.';
  }

}

console.log(ClassWithStaticMethod.staticProperty);
// output: "someValue"
console.log(ClassWithStaticMethod.staticMethod());
// output: "static method has been called."

Update property value to include single quotes


import { bindable } from 'aurelia-framework';

export class UiErrorMessageCustomElement {
    @bindable errorSource;

    errorSourceChanged() {
        if (this.errorSource) {
            this.error = {};
            this.error.status = this.errorSource.status;
            this.error.statusText = this.errorSource.statusText;
            if (this.errorSource.bodyUsed && this.errorSource.bodyUsed === false) {
                this.errorSource.json().then(response => {
                    if (response.message) {
                        this.error.message = response.message;
                    }
                })
            } else {
                if (this.errorSource.body && this.errorSource.body.message) {
                    this.error.message = this.errorSource.body.message;
                }
            }
        } else {
            this.error = null;
        }
    }
}

import { bindable } from 'aurelia-framework';

export class UiErrorMessageCustomElement {
    @bindable errorSource;

    errorSourceChanged() {
        if (this.errorSource) {
            this.error = {};
            this.error.status = this.errorSource.status;
            this.error.statusText = this.errorSource.statusText;

            if ('bodyUsed' in this.errorSource && this.errorSource.bodyUsed === false) {
                this.errorSource.json().then(response => {
                    if (response.message) {
                        this.error.message = response.message;
                    }
                })
            } else {
                if (this.errorSource.body && this.errorSource.body.message) {
                    this.error.message = this.errorSource.body.message;
                }
            }
        } else {
            this.error = null;
        }
    }
}

Fix error message so they display something useful


function Player (name, roomId, playerId, color, socket, socketId) {
	this.name = name;
	this.roomId = roomId;
	this.playerId = playerId;
	this.color = color;
	this.socket = socket;
	this.socketId = socketId;

	this.startMeasuringLatency();
}

Player.prototype.startMeasuringLatency = function () {
	var that = this;
	var lastSentTime;
	var lastSentRttResponseReceived = true;

	that.socket.on('connection.rtt.fromclient', function (data) {
		lastSentRttResponseReceived = true;
		var currentTime = new Date().getTime();
		that.latency = currentTime - lastSentTime;
	});

	var rttMeasure = setInterval(function () {
		if (lastSentRttResponseReceived) {
			that.socket.emit('connection.rtt.toclient');
			lastSentTime = new Date().getTime();
			lastSentRttResponseReceived = false;
		}
	}, 1000);
}

Player.prototype.getState = function () {
	return {
		name: this.name,
		playerId: this.playerId,
		socketId: this.socketId,
		color: this.color
	};
}

module.exports = Player;

function Player (name, roomId, playerId, color, socket, socketId) {
	this.name = name;
	this.roomId = roomId;
	this.playerId = playerId;
	this.color = color;
	this.socket = socket;
	this.socketId = socketId;

	this.startMeasuringLatency();
}

Player.prototype.startMeasuringLatency = function () {
	var that = this;
	var lastSentTime;
	var lastSentRttResponseReceived = true;

	that.socket.on('connection.rtt.fromclient', function (data) {
		lastSentRttResponseReceived = true;
		var currentTime = new Date().getTime();
		that.latency = currentTime - lastSentTime / 2; // Latency is half rtt
	});

	var rttMeasure = setInterval(function () {
		if (lastSentRttResponseReceived) {
			that.socket.emit('connection.rtt.toclient');
			lastSentTime = new Date().getTime();
			lastSentRttResponseReceived = false;
		}
	}, 1000);
}

Player.prototype.getState = function () {
	return {
		name: this.name,
		playerId: this.playerId,
		socketId: this.socketId,
		color: this.color
	};
}

module.exports = Player;

Update latency calculating mechanism to return latency is half of rtt


var exec = require('cordova/exec');
var cordova = require('cordova');

function OnePassword() {

}

OnePassword.prototype.findLoginForUrl = function (success, error, url) {
    exec(success, error, "OnePassword", "findLoginForUrl", [url]);
};

OnePassword.prototype.fillItemIntoWebView = function (success, error, url) {
    exec(success, error, "OnePassword", "fillItemIntoWebView", [url]);
};

OnePassword.prototype.storeLoginForUrl = function (success, error, url, username, password) {
    exec(success, error, "OnePassword", "storeLoginForURLString", [username, password, url, title, sectionTitle]);
};

module.exports = new OnePassword();

var exec = require('cordova/exec');
var cordova = require('cordova');

function OnePassword() {

}

OnePassword.prototype.findLoginForUrl = function (success, error, url) {
    exec(success, error, "OnePassword", "findLoginForUrl", [url]);
};

OnePassword.prototype.fillItemIntoWebView = function (success, error, url) {
    exec(success, error, "OnePassword", "fillItemIntoWebView", [url]);
};

OnePassword.prototype.storeLoginForUrl = function (success, error, url, username, password, title, sectionTitle) {
    exec(success, error, "OnePassword", "storeLoginForURLString", [username, password, url, title, sectionTitle]);
};

module.exports = new OnePassword();

Fix the OnePassword.storeLoginForUrl method params


/*global jest, jasmine, describe, it, expect*/

jest.dontMock('../');

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

describe('exports', function() {
    it('should provide activate function', function() {
        expect(hotkey.activate).toEqual(jasmine.any(Function));
    });
    it('should provide disable function', function() {
        expect(hotkey.disable).toEqual(jasmine.any(Function));
    });
    it('should provide Mixin', function() {
        expect(hotkey.Mixin).toEqual(jasmine.any(Function));
    });
});

/*global jest, jasmine, describe, it, expect*/

jest.dontMock('../');

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

describe('exports', function() {
    it('should provide activate function', function() {
        expect(hotkey.activate).toEqual(jasmine.any(Function));
    });
    it('should provide disable function', function() {
        expect(hotkey.disable).toEqual(jasmine.any(Function));
    });
    it('should provide addHandler function', function() {
        expect(hotkey.addHandler).toEqual(jasmine.any(Function));
    });
    it('should provide removeHandler function', function() {
        expect(hotkey.removeHandler).toEqual(jasmine.any(Function));
    });
    it('should provide Mixin', function() {
        expect(hotkey.Mixin).toEqual(jasmine.any(Function));
    });
});

Add tests for presence of addHandler and removeHandler.


var keystone = require('../../../');
	var signin = keystone.get('signin redirect') || 'signin';
	if (signin != 'signin') {
		res.redirect(signin);
	} else {
		keystone.render(req, res, signin, {
			submitted: req.body,
			from: req.query.from,
			logo: keystone.get('signin logo'),
		});
	}
};

var keystone = require('../../../');
var signin = keystone.get('signin redirect') || 'signin';
if (signin !== 'signin') {
	res.redirect(signin);
} else {
	keystone.render(req, res, signin, {
		submitted: req.body,
		from: req.query.from,
		logo: keystone.get('signin logo'),
	});

};

Fix strict quality check and extra }


#!/usr/bin/env node
var express = require('express');
var simpleFsRest = require('simple-fs-rest');
var app = express();

var MAX_TIME = 100;

// Link the REST Service to anything under /api. ex: /api/users/
app.use('/api', function(req, res, next) {
  var server = simpleFsRest();

  setTimeout(function() {
    server(req, res, next);
  }, Math.random() * MAX_TIME);
});

app.listen(8081);

#!/usr/bin/env node
var express = require('express');
var simpleFsRest = require('simple-fs-rest');
var app = express();

var TIME_DELAY = 135;

// Link the REST Service to anything under /api. ex: /api/users/
app.use('/api', function(req, res, next) {
  var server = simpleFsRest();

  setTimeout(function() {
    server(req, res, next);
  }, TIME_DELAY);
});

app.listen(8081);

Make ajax have constant latency


var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

//Deliver index.html with client javascript code
app.get('/', function(req, res){
    res.sendFile(__dirname + '/index.html');
});

//Create server socket for client connection
io.on('connection', function(socket){
    console.log('a user connected');

    socket.on('chat message', function (msg) {
        console.log('message: ' + msg);
        io.emit('chat messages', msg);
    })

    //socket.on('disconnect', function(){  //Create disconnect, if client refreshes/exits index.html
    //    console.log('user disconnect');
    //});
});

http.listen(3000, function(){
    console.log('listening on *:3000');
});

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

//Deliver index.html with client javascript code
app.get('/', function(req, res){
    res.sendFile(__dirname + '/index.html');
});

//Create server socket for client connection
io.on('connection', function(socket){
    console.log('a user connected');

    socket.on('chat message', function (msg) {
        console.log('message: ' + msg);
        io.emit('chat messages', msg);
    })

    //socket.on('disconnect', function(){  //Create disconnect, if client refreshes/exits index.html
    //    console.log('user disconnect');
    //});
});

var port = normalizePort(process.env.PORT || '3000');
http.listen(port, function(){
    console.log('listening on port ' + port);
});

FIX Use port from environment


var fs = require('fs');

function copyFile(source, target) {
  console.log('Copying ' + source + ' to ' + target + '...');
  return new Promise(function(resolve, reject) {
    var input = fs.createReadStream(source), output;
    input.on('error', reject);
    output = fs.createWriteStream(target);
    output.on('error', reject);
    output.on('finish', resolve);
    input.pipe(output);
  });
}

copyFile('node_modules/less/dist/less.js', 'lessc.js')
  .then(function () {
    process.exit(0);
  })
  .catch(function (error) {
    console.error(error.message);
    process.exit(1);
  });

var ncp = require('ncp').ncp,
    source = 'node_modules/less/dist/less.js',
    target = 'lessc.js';

console.log('Copying ' + source + ' to ' + target + '...');
ncp(source, target, function (error) {
  if (error) {
    console.error(error.message);
    process.exit(1);
  } else {
    process.exit(0);
  }
});

Use the ncp npm module to copy lessc.js to the root directory


// This is called on every message. It can reject a message, or transform it, or let it through.

export default class MessageProxy {
	lastMessage = {}
	spamInterval = 1000

	sniff(message) {
		const now = (new Date()).getTime();
		const author = message.chat.username;
		var rejected = false;
		const lastMessage = this.lastMessage[author];
		// The difference is in milliseconds.
		if (lastMessage && ((now - lastMessage) < this.spamInterval))
			rejected = true;

		this.lastMessage[author] = now;
		if (rejected)
			return Promise.reject();
		else
			return Promise.resolve(message);
	}
}

// This is called on every message. It can reject a message, or transform it, or let it through.

export default class MessageProxy {
	lastMessage = {}
	spamInterval = 1000

	sniff(message) {
		const now = (new Date()).getTime();
		const author = message.from.id;
		var rejected = false;
		const lastMessage = this.lastMessage[author];
		// The difference is in milliseconds.
		if (lastMessage && ((now - lastMessage) < this.spamInterval))
			rejected = true;

		this.lastMessage[author] = now;
		if (rejected)
			return Promise.reject();
		else
			return Promise.resolve(message);
	}
}

Fix bug wih anti-flood, now using from, not author


'use strict'
const schemaValidator = module.exports = { }

schemaValidator.validate = function (resources) {
  Object.keys(resources).forEach(resource => {
    Object.keys(resources[resource].attributes).forEach(attribute => {
      let joiSchema = resources[resource].attributes[attribute]
      if (!joiSchema._settings) return

      let types = joiSchema._settings.__one || joiSchema._settings.__many
      types.forEach(type => {
        if (!resources[type]) {
          throw new Error(`Error: '${resource}'.'${attribute}' is defined to hold a relation with '${type}', but '${type}' is not a valid resource name!`)
        }
      })
      let foreignRelation = joiSchema._settings.__as
      if (!foreignRelation) return

      let backReference = resources[types[0]].attributes[foreignRelation]
      if (!backReference) {
        throw new Error(`Error: '${resource}'.'${attribute}' is defined as being a foreign relation to the primary '${types[0]}'.'${foreignRelation}', but that primary relationship does not exist!`)
      }
    })
  })
}

'use strict'
const schemaValidator = module.exports = { }

schemaValidator.validate = function (resources) {
  Object.keys(resources).forEach(resource => {
    Object.keys(resources[resource].attributes).forEach(attribute => {
      let joiSchema = resources[resource].attributes[attribute]
      if (!joiSchema._settings) return

      let types = joiSchema._settings.__one || joiSchema._settings.__many
      types.forEach(type => {
        if (!resources[type]) {
          throw new Error(`'${resource}'.'${attribute}' is defined to hold a relation with '${type}', but '${type}' is not a valid resource name!`)
        }
      })
      let foreignRelation = joiSchema._settings.__as
      if (!foreignRelation) return

      let backReference = resources[types[0]].attributes[foreignRelation]
      if (!backReference) {
        throw new Error(`'${resource}'.'${attribute}' is defined as being a foreign relation to the primary '${types[0]}'.'${foreignRelation}', but that primary relationship does not exist!`)
      }
    })
  })
}

Validate resource schema are valid on startup


const ExtractTextPlugin = require('extract-text-webpack-plugin');
const glob = require("glob");

module.exports = {
  entry: glob.sync("./dist/css/**/*.css"),
  output: {
    path: __dirname + '/dist',
    filename: 'pivotal-ui.js'
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        loader: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: 'css-loader'
        })
      },
      {
        test: /\.(eot|ttf|woff)$/,
        loader: 'url-loader'
      },
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        loaders: 'file-loader!image-webpack-loader'
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin("components.css")
  ]
};

const ExtractTextPlugin = require('extract-text-webpack-plugin');
const glob = require("glob");

module.exports = {
  entry: glob.sync("./dist/css/**/*.css"),
  output: {
    path: __dirname + '/dist',
    filename: 'pivotal-ui.js'
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        loader: ExtractTextPlugin.extract({
          fallback: 'style-loader',
          use: 'css-loader'
        })
      },
      {
        test: /\.(eot|ttf|woff)$/,
        loader: 'url-loader'
      },
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        loaders: [
          'file-loader?hash=sha512&digest=hex&name=[hash].[ext]',
          'image-webpack-loader?bypassOnDebug&optimizationLevel=7&interlaced=false'
        ]
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin("components.css")
  ]
};

Revert "Simplify webpack image loading"


function aC(r, n) { if (r) { r.appendChild(n); } else { dumpln("aC->rM"); rM(n); } }
function iB(r, n) { if (r) { r.parentNode.insertBefore(n, r); } else { dumpln("iB->rM"); rM(n); } }
function rM(n)    { n.parentNode.removeChild(n); }

function getKeysFromHash(h)
{
  var a = [];
  for (var p in h)
    a.push(p);
  return a;
}

function isPrimitive(v)
{
// NB: document.all is == but not ===
// NB: typeof== is optimized by spidermonkey
return (v === null || v === undefined || typeof v == "boolean" || typeof v == "number" || typeof v == "string");
}

/*

function insertAsFirstChild(p, n)
{
  p.insertBefore(n, p.firstChild);
}

function removeChildAt(p, i)
{
  var n = p.childNodes[i];

  p.removeChild(n);
}
*/

function aC(r, n) { if (r) { r.appendChild(n); } else { dumpln("aC->rM"); rM(n); } }
function iB(r, n) { if (r) { r.parentNode.insertBefore(n, r); } else { dumpln("iB->rM"); rM(n); } }
function rM(n)    { n.parentNode.removeChild(n); }

function getKeysFromHash(h)
{
  var a = [];
  for (var p in h)
    a.push(p);
  return a;
}

function isPrimitive(v)
{
// NB: document.all is == but not ===
// NB: typeof== is optimized by spidermonkey
return (v === null || v === undefined || typeof v == "boolean" || typeof v == "number" || typeof v == "string");
}

function errorToString(e)
{
  try {
    return "" + e;
  } catch (e2) {
    return "Can't toString the error!!";
  }
}

/*

function insertAsFirstChild(p, n)
{
  p.insertBefore(n, p.firstChild);
}

function removeChildAt(p, i)
{
  var n = p.childNodes[i];

  p.removeChild(n);
}
*/

Move errorToString to global scope, because it's also used by another module and useful for manual reduction


var SumOfMultiples = require('./sum-of-multiples');

describe('SumOfMultiples', function () {
  it('to 1', function () {
    expect(SumOfMultiples().to(1)).toBe(0);
  });

  xit('to 3', function () {
    expect(SumOfMultiples().to(4)).toBe(3);
  });

  xit('to 10', function () {
    expect(SumOfMultiples().to(10)).toBe(23);
  });

  xit('to 1000', function () {
    expect(SumOfMultiples().to(1000)).toBe(233168);
  });

  xit('[7, 13, 17] to 20', function () {
    expect(SumOfMultiples([7, 13, 17]).to(20)).toBe(51);
  });

  xit('[43, 47] to 10000', function () {
    expect(SumOfMultiples([43, 47]).to(10000)).toBe(2203160);
  });
});

var SumOfMultiples = require('./sum-of-multiples');

describe('SumOfMultiples', function () {
  it('to 1', function () {
    expect(SumOfMultiples().to(1)).toBe(0);
  });

  xit('to 3', function () {
    expect(SumOfMultiples().to(4)).toBe(3);
  });

  xit('to 10', function () {
    expect(SumOfMultiples().to(10)).toBe(23);
  });

  xit('to 1000', function () {
    expect(SumOfMultiples().to(1000)).toBe(233168);
  });

  xit('[7, 13, 17] to 20', function () {
    expect(SumOfMultiples([7, 13, 17]).to(20)).toBe(51);
  });

  xit('[4, 6] to 15', function () {
    expect(SumOfMultiples([4, 6]).to(15)).toBe(30);
  });

  xit('[5, 6, 8] to 150', function () {
    expect(SumOfMultiples([5, 6, 8]).to(150)).toBe(4419);
  });

  xit('[43, 47] to 10000', function () {
    expect(SumOfMultiples([43, 47]).to(10000)).toBe(2203160);
  });
});

Add test cases to Sum of Multiples


import Joi from 'joi'
import moduleSchema from './properties/module'

export const schema = Joi.object({
  module: moduleSchema,
  resolve: Joi.any(),
  output: Joi.any(),
  entry: Joi.any(),
  plugins: Joi.any(),
  devtool: Joi.any(),
  externals: Joi.any(),
  node: Joi.any(),
  stats: Joi.any(),
  context: Joi.any(),
  debug: Joi.any(),
  devServer: Joi.any(),

  // Plugins
  postcss: Joi.any(),
  eslint: Joi.any(),
  tslint: Joi.any(),
  metadata: Joi.any(),
})//.unknown()

export default function validate(config, schema_ = schema) {
  const options = {
    abortEarly: false,
  }
  try {
    Joi.assert(config, schema_, options)
  } catch (err) {
    return err
  }

  return null
}

import Joi from 'joi'
import moduleSchema from './properties/module'

export const schema = Joi.object({
  amd: Joi.any(),
  bail: Joi.any(),
  cache: Joi.any(),
  context: Joi.any(),
  debug: Joi.any(),
  devServer: Joi.any(),
  devtool: Joi.any(),
  entry: Joi.any(),
  externals: Joi.any(),
  loader: Joi.any(),
  module: moduleSchema,
  node: Joi.any(),
  output: Joi.any(),
  plugins: Joi.any(),
  profile: Joi.any(),
  recordsInputPath: Joi.any(),
  recordsOutputPath: Joi.any(),
  recordsPath: Joi.any(),
  resolve: Joi.any(),
  resolveLoader: Joi.any(),
  stats: Joi.any(),
  target: Joi.any(),

  // Plugins
  postcss: Joi.any(),
  eslint: Joi.any(),
  tslint: Joi.any(),
  metadata: Joi.any(),
})//.unknown()

export default function validate(config, schema_ = schema) {
  const options = {
    abortEarly: false,
  }
  try {
    Joi.assert(config, schema_, options)
  } catch (err) {
    return err
  }

  return null
}

Add missing top level properties


'use strict';

/**
@module storex
*/
module.exports = {
	// Folders.
	Actions: require('./actions'),
	// Files.
	Action: require('./action'),
	createStore: require('./createStore')
};

'use strict';

/**
@module storex
*/
module.exports = {
	// Folders.
	Actions: require('./actions'),
	// Files.
	Action: require('./action'),
	createStore: require('./createStore'),
	Store: require('./store')
};

Add Store prop to main module.


import React from 'react';
import ReactDOM from 'react-dom';
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import rootReducer from './redux/rootReducer';

import Frontend from './FrontendApp';
import Editor from './editor/EditorApp';
import './index.css';

const store = createStore(rootReducer);

const App = process.env.NODE_ENV === "development"
  ? Editor
  : Frontend;

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);

import React from 'react';
import ReactDOM from 'react-dom';
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import rootReducer from './redux/rootReducer';

import Frontend from './FrontendApp';
import './index.css';

const store = createStore(rootReducer);

const renderApp = (Component) => (
  ReactDOM.render(
    <Provider store={store}>
      <Component />
    </Provider>,
    document.getElementById('root')
  )
);

if (process.env.NODE_ENV === "development") {
  require.ensure([], (require) => {
    const Editor = require('./editor/EditorApp').default;
    renderApp(Editor);
  });
} else {
  renderApp(Frontend);
}

Use code splitting to pack editor and dependencies in own chunk


module.exports.sayHello = function (name) {
    return "Hello " + name + "."
};

module.exports.sayHello = function (name) {
    return "Hello " + name + ".";
};

Add breaking error to test slack notifications on error


/* eslint-disable import/default */

import React from 'react';
import {render} from 'react-dom';
import { Provider } from 'react-redux';
import { Router, browserHistory } from 'react-router';
import routes from './routes';
import configureStore from './store/configureStore';
require('./favicon.ico'); // Tell webpack to load favicon.ico
import { syncHistoryWithStore } from 'react-router-redux';

const store = configureStore();

// Create an enhanced history that syncs navigation events with the store
const history = syncHistoryWithStore(browserHistory, store);

render(
  <Provider store={store}>
    <Router history={history} routes={routes} />
  </Provider>, document.getElementById('app')
);

/* eslint-disable import/default */

import React from 'react';
import {render} from 'react-dom';
import { Provider } from 'react-redux';
import { Router, hashHistory } from 'react-router';
import routes from './routes';
import configureStore from './store/configureStore';
require('./favicon.ico'); // Tell webpack to load favicon.ico
import { syncHistoryWithStore } from 'react-router-redux';

const store = configureStore();

// Create an enhanced history that syncs navigation events with the store
const history = syncHistoryWithStore(hashHistory, store);

render(
  <Provider store={store}>
    <Router history={history} routes={routes} />
  </Provider>, document.getElementById('app')
);

Use hash history for react-router.


import Button from './Button';
import ButtonGroup from './ButtonGroup';
import Card from './Card';
import Dialog from './Dialog/Dialog';
import DialogContent from './Dialog/DialogContent';
import DialogHeader from './Dialog/DialogHeader';
import DialogFooter from './Dialog/DialogFooter';
import Icon from './Icon';
import FormContainer from './FormContainer';
import FormSlot from './FormSlot';
import List from './List';
import Table from './Table';
import TextInput from './TextInput';
import Toolbar from './Toolbar';
import Tab from './Tab';
import TabGroup from './TabGroup';
import Checkbox from './Checkbox';

import {
	AppHeader,
	Cell,
	ContentCell,
	Drawer,
	Grid,
	GridContainer,
	GridFrame,
	VerticalSpace,
} from './layout';

export {
	Button,
	ButtonGroup,
	Card,
	Dialog,
	DialogContent,
	DialogHeader,
	DialogFooter,
	FormContainer,
	FormSlot,
	Icon,
	List,
	Table,
	TextInput,
	Toolbar,
	AppHeader,
	Cell,
	ContentCell,
	Drawer,
	Grid,
	GridContainer,
	GridFrame,
	VerticalSpace,
	Tab,
	TabGroup,
	Checkbox
};

import Button from './Button';
import ButtonGroup from './ButtonGroup';
import Card from './Card';
import Dialog from './Dialog/Dialog';
import DialogContent from './Dialog/DialogContent';
import DialogHeader from './Dialog/DialogHeader';
import DialogFooter from './Dialog/DialogFooter';
import Icon from './Icon';
import FormContainer from './FormContainer';
import FormSlot from './FormSlot';
import List from './List';
import Table from './Table';
import TextInput from './TextInput';
import Toolbar from './Toolbar';
import Tab from './Tab';
import TabGroup from './TabGroup';
import Checkbox from './Checkbox';
import RadioButton from './RadioButton';
import RadioSelector from './RadioSelector';
import prompts from './utils/prompts';

import {
	AppHeader,
	Cell,
	ContentCell,
	Drawer,
	Grid,
	GridContainer,
	GridFrame,
	VerticalSpace,
} from './layout';

export {
	Button,
	ButtonGroup,
	Card,
	Dialog,
	DialogContent,
	DialogHeader,
	DialogFooter,
	FormContainer,
	FormSlot,
	Icon,
	List,
	Table,
	TextInput,
	Toolbar,
	AppHeader,
	Cell,
	ContentCell,
	Drawer,
	Grid,
	GridContainer,
	GridFrame,
	VerticalSpace,
	Tab,
	TabGroup,
	Checkbox,
	RadioSelector,
	RadioButton,
	prompts
};

Add new stuff to main export


/* eslint-disable no-console */
import { createFilter } from 'rollup-pluginutils';
import { resolve } from 'source-map-resolve';
import { readFile } from 'fs';
import { promisify } from './utils';

const readFileAsync = promisify(readFile);
const resolveSourceMapAsync = promisify(resolve);

export default function sourcemaps({ include, exclude } = {}) {
  const filter = createFilter(include, exclude);

  return {
    async load(id) {
      if (!filter(id)) {
        return null;
      }

      let code;
      try {
        code = await readFileAsync(id, 'utf8');
      } catch (err) {
        // Failed, let Rollup deal with it
        return null;
      }

      let sourceMap;
      try {
        sourceMap = await resolveSourceMapAsync(code, id, readFile);
      } catch (err) {
        console.error(`rollup-plugin-sourcemaps: Failed resolving source map from ${id}: ${err}`);
        return code;
      }

      // No source map detected, return code
      if (sourceMap === null) {
        return code;
      }

      const { map, sourcesContent } = sourceMap;

      map.sourcesContent = sourcesContent;

      return { code, map };
    },
  };
}

/* eslint-disable no-console */
import { createFilter } from 'rollup-pluginutils';
import { resolve } from 'source-map-resolve';
import { readFile } from 'fs';
import { promisify } from './utils';

const readFileAsync = promisify(readFile);
const resolveSourceMapAsync = promisify(resolve);

export default function sourcemaps({ include, exclude } = {}) {
  const filter = createFilter(include, exclude);

  return {
    name: 'sourcemaps',

    async load(id) {
      if (!filter(id)) {
        return null;
      }

      let code;
      try {
        code = await readFileAsync(id, 'utf8');
      } catch (err) {
        // Failed, let Rollup deal with it
        return null;
      }

      let sourceMap;
      try {
        sourceMap = await resolveSourceMapAsync(code, id, readFile);
      } catch (err) {
        console.error(`rollup-plugin-sourcemaps: Failed resolving source map from ${id}: ${err}`);
        return code;
      }

      // No source map detected, return code
      if (sourceMap === null) {
        return code;
      }

      const { map, sourcesContent } = sourceMap;

      map.sourcesContent = sourcesContent;

      return { code, map };
    },
  };
}

Add name property to plugin object


var execSync = require('child_process').execSync;
var Interactive = require('./interactive');

function GitAddAndCommit(options) {
	if (options.help) {
		console.log('help screen');
	} else if (options.interactive) {
		new Interactive().run();
	} else {
		this.normal();
	}
}

var proto = GitAddAndCommit.prototype;

proto.normal = function() {
	try {
		var args = process.argv.slice(2);
		var fileGlob = args[0];
		var commitMessage = args[1];

		execSync('git add -- *' + fileGlob + '*');
		execSync('git commit -m "' + commitMessage + '"')
	} catch (e) {
		console.log(e);
		console.log('Resetting added files...');
		execSync('git reset .');
	}
};

module.exports = GitAddAndCommit;

var execSync = require('child_process').execSync;
var Interactive = require('./interactive');

function GitAddAndCommit(options) {
	if (options.help) {
		console.log('help screen');
	} else if (options.interactive) {
		new Interactive().run();
	} else {
		this.normal();
	}
}

var proto = GitAddAndCommit.prototype;

proto.normal = function() {
	try {
		var args = process.argv.slice(2);
		var fileGlob = args[0];
		var commitMessage = args[1];

		execSync('git add -- *' + fileGlob + '*');
		execSync('git commit -m "' + commitMessage + '"')
	} catch (e) {
		console.log('Encountered error -- aborting.');
		process.stdin.write('Reset added files...');
		execSync('git reset .');
		process.stdin.write('Done.');
		console.log();
	}
};

module.exports = GitAddAndCommit;

Reset files when an error is thrown


'use babel'

/* @flow */

module.exports = function promisify(callback: Function): Function {
  return function promisified(){
    const parameters = arguments
    const parametersLength = arguments.length + 1
    return new Promise((resolve, reject) => {
      Array.prototype.push.call(parameters, function(error, data) {
        if (error) {
          reject(error)
        } else resolve(data)
      })
      if (parametersLength === 1) {
        callback.call(this, parameters[0])
      } else if (parametersLength === 2) {
        callback.call(this, parameters[0], parameters[1])
      } else if (parametersLength === 3) {
        callback.call(this, parameters[0], parameters[1], parameters[2])
      } else if (parametersLength === 4) {
        callback.call(this, parameters[0], parameters[1], parameters[2], parameters[3])
      } else {
        callback.apply(this, parameters)
      }
    })
  }
}

'use babel'

/* @flow */

module.exports = function promisify(callback: Function): Function {
  return function promisified(){
    const parameters = Array.from(arguments)
    const parametersLength = parameters.length + 1
    return new Promise((resolve, reject) => {
      parameters.push(function(error, data) {
        if (error) {
          reject(error)
        } else resolve(data)
      })
      if (parametersLength === 1) {
        callback.call(this, parameters[0])
      } else if (parametersLength === 2) {
        callback.call(this, parameters[0], parameters[1])
      } else if (parametersLength === 3) {
        callback.call(this, parameters[0], parameters[1], parameters[2])
      } else if (parametersLength === 4) {
        callback.call(this, parameters[0], parameters[1], parameters[2], parameters[3])
      } else {
        callback.apply(this, parameters)
      }
    })
  }
}

Use some best practices Learnt from the node.js core peeps


import americano from 'americano';
import path from 'path-extra';

import { makeLogger } from './helpers';

let log = makeLogger('index');

let application = (options = {}, callback) => {
    options.name   = 'Kresus';
    options.root   = options.root || path.join(__dirname, '..');
    options.port   = process.env.PORT || 9876;
    options.host   = process.env.HOST || '127.0.0.1';

    // If we try to import 'init', this has to be done at the global scope
    // level. In this case, we will import init and its transitive closure of
    // imports before americano is initialized. As a matter of fact, default
    // parameters of americano will be taken into account (no routes, no
    // models, no standalone cozydb). So the 'init' import has to be
    // synchronous, at the last minute.
    americano.start(options, (err, app, server) => {
        if (err) {
            return log.error(`Error when starting americano: ${ err }`);
        }
        require('./init')(app, server, callback);
    });
};

if (typeof module.parent === 'undefined' || !module.parent)
    application();

module.exports = application;

import americano from 'americano';
import path from 'path-extra';

import { makeLogger } from './helpers';

let log = makeLogger('index');

let application = (options = {}, callback) => {
    options.name   = 'Kresus';
    options.root   = options.root || path.join(__dirname, '..');
    options.port   = process.env.PORT || 9876;
    options.host   = process.env.HOST || '127.0.0.1';

    // If we try to import 'init', this has to be done at the global scope
    // level. In this case, we will import init and its transitive closure of
    // imports before americano is initialized. As a matter of fact, default
    // parameters of americano will be taken into account (no routes, no
    // models, no standalone cozydb). So the 'init' import has to be
    // synchronous, at the last minute.
    americano.start(options, (err, app, server) => {
        if (err) {
            return log.error(`Error when starting americano: ${ err }`);
        }

        // Raise the timeout limit, since some banking modules can be quite
        // long at fetching new operations. Time is in milliseconds.
        server.timeout = 5 * 60 * 1000;

        require('./init')(app, server, callback);
    });
};

if (typeof module.parent === 'undefined' || !module.parent)
    application();

module.exports = application;

Raise the timeout limit for slow banking modules;


/**
 *  Copyright (c) 2015, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 */

// Helpers for creating connection types in the schema
export {
  connectionArgs,
  connectionDefinitions,
} from './connection/connection.js';

// Helpers for creating connections from arrays
export {
  connectionFromArray,
  connectionFromArraySlice,
  connectionFromPromisedArray,
  connectionFromPromisedArraySlice,
  cursorForObjectInConnection,
  cursorToOffset,
  getOffsetWithDefault,
  offsetToCursor,
} from './connection/arrayconnection.js';

// Helper for creating mutations with client mutation IDs
export {
  mutationWithClientMutationId,
} from './mutation/mutation.js';

// Helper for creating node definitions
export {
  nodeDefinitions,
} from './node/node.js';

// Utilities for creating global IDs in systems that don't have them.
export {
  fromGlobalId,
  globalIdField,
  toGlobalId,
} from './node/node.js';

/**
 *  Copyright (c) 2015, Facebook, Inc.
 *  All rights reserved.
 *
 *  This source code is licensed under the BSD-style license found in the
 *  LICENSE file in the root directory of this source tree. An additional grant
 *  of patent rights can be found in the PATENTS file in the same directory.
 */

// Helpers for creating connection types in the schema
export {
  backwardConnectionArgs,
  connectionArgs,
  connectionDefinitions,
  forwardConnectionArgs,
} from './connection/connection.js';

// Helpers for creating connections from arrays
export {
  connectionFromArray,
  connectionFromArraySlice,
  connectionFromPromisedArray,
  connectionFromPromisedArraySlice,
  cursorForObjectInConnection,
  cursorToOffset,
  getOffsetWithDefault,
  offsetToCursor,
} from './connection/arrayconnection.js';

// Helper for creating mutations with client mutation IDs
export {
  mutationWithClientMutationId,
} from './mutation/mutation.js';

// Helper for creating node definitions
export {
  nodeDefinitions,
} from './node/node.js';

// Utilities for creating global IDs in systems that don't have them.
export {
  fromGlobalId,
  globalIdField,
  toGlobalId,
} from './node/node.js';

Add missing exports for backwardConnectionArgs and forwardConnectionArgs


import React from 'react';

const {PropTypes} = React;
const {span} = React.DOM;

const Status = {
  PENDING: 'pending',
  LOADING: 'loading',
  LOADED: 'loaded',
  FAILED: 'failed',
};

export default React.createClass({
  displayName: 'ImageLoader',
  propTypes: {
    wrapper: PropTypes.func,
    className: PropTypes.string,
  },

  getInitialState() {
    return {status: this.props.src ? Status.LOADING : Status.PENDING};
  },

  getDefaultProps() {
    return {wrapper: span};
  },

  getClassName() {
    let className = `imageloader ${this.state.status}`;
    if (this.props.className) className = `${className} ${this.props.className}`;
    return className;
  },

  render() {
    const wrapperProps = [{className: this.getClassName()}];
    return this.props.wrapper(...wrapperProps);
  },
});

import React from 'react';

const {PropTypes} = React;
const {span} = React.DOM;

const Status = {
  PENDING: 'pending',
  LOADING: 'loading',
  LOADED: 'loaded',
  FAILED: 'failed',
};

export default React.createClass({
  displayName: 'ImageLoader',
  propTypes: {
    wrapper: PropTypes.func,
    className: PropTypes.string,
  },

  getInitialState() {
    return {status: this.props.src ? Status.LOADING : Status.PENDING};
  },

  getDefaultProps() {
    return {wrapper: span};
  },

  componentDidMount() {
    if (this.state.status === Status.LOADING) {
      this.createLoader();
    }
  },

  getClassName() {
    let className = `imageloader ${this.state.status}`;
    if (this.props.className) className = `${className} ${this.props.className}`;
    return className;
  },

  createLoader() {
    this.destroyLoader();  // We can only have one loader at a time.

    this.img = new Image();
    this.img.addEventListener('load', this.handleLoad);
    this.img.addEventListener('error', this.handleError);
    this.img.src = this.props.src;
  },

  destroyLoader() {
    if (this.img) {
      this.img.removeEventListener('load', this.handleLoad);
      this.img.removeEventListener('error', this.handleError);
      delete this.img;
    }
  },

  handleLoad(event) {
    this.destroyLoader();
    this.setState({status: Status.LOADED});

    if (this.props.onLoad) this.props.onLoad(event);
  },

  handleError(error) {
    this.destroyLoader();
    this.setState({status: Status.FAILED});

    if (this.props.onError) this.props.onError(error);
  },

  render() {
    let wrapperProps = [{className: this.getClassName()}];

    switch (this.state.status) {
      case Status.LOADED:
        wrapperProps.push(<img src={this.props.src} />);
        break;
    }

    return this.props.wrapper(...wrapperProps);
  },
});

Implement the basic loading mechanism


import Parallax from './js/parallax';
import Share from './js/share';

require('./sass/main.scss');

/**
 * Enable parallax for the post list
 */
Array.prototype.forEach.call(document.querySelectorAll('.post-item'), elm => new Parallax(elm, 50));

/**
 * Enable share buttons for the post detail page
 */
if (document.querySelector('.post-detail-wrapper .post-share')) {
  new Share(document.querySelector('.post-detail-wrapper .post-share')).render();
}

/**
 *  Set target to new windows for all hyperlinks in the post content
 */
(() => {
  const links = document.querySelectorAll('.post-content a');

  Array.prototype.forEach.call(links, (link) => {
    if (/^(https?|ftp|\/)/.test(link.href)) {
      link.setAttribute('target', '_blank');
    }
  });
})();

Set target to _blank for all hyperlinks in the post content


// Loaded ready states
const loadedStates = ['interactive', 'complete'];

// Return Promise
const whenDomReady = (cb, doc) => new Promise(resolve => {
	// Allow doc to be passed in as the lone first param
	if (cb && typeof cb !== 'function') {
		doc = cb;
		cb = null;
	}

	// Use global document if we don't have one
	doc = doc || window.document;

	// Handle DOM load
	const done = () => resolve(cb && setTimeout(cb));

	// Resolve now if DOM has already loaded
	// Otherwise wait for DOMContentLoaded
	if (loadedStates.includes(doc.readyState)) {
		done();
	} else {
		doc.addEventListener('DOMContentLoaded', done);
	}
});

// Promise chain helper
whenDomReady.resume = doc => val => whenDomReady(doc).then(() => val);

export default whenDomReady;

// Loaded ready states
const loadedStates = ['interactive', 'complete'];

// Return Promise
const whenDomReady = (cb, doc) => new Promise(resolve => {
	// Allow doc to be passed in as the lone first param
	if (cb && typeof cb !== 'function') {
		doc = cb;
		cb = null;
	}

	// Use global document if we don't have one
	doc = doc || window.document;

	// Handle DOM load
	const done = () => resolve(void (cb && setTimeout(cb)));

	// Resolve now if DOM has already loaded
	// Otherwise wait for DOMContentLoaded
	if (loadedStates.includes(doc.readyState)) {
		done();
	} else {
		doc.addEventListener('DOMContentLoaded', done);
	}
});

// Promise chain helper
whenDomReady.resume = doc => val => whenDomReady(doc).then(() => val);

export default whenDomReady;

Make sure no return value is resolved


'use strict';

/* eslint no-unused-vars: 0 */

module.exports.read = function read( toFind ) {
    // TODO: hit bucket and read

    return Promise.reject({ code: 501, message: 'Not implemented.' });
};

module.exports.write = function write( toWrite ) {
    // TODO: hit bucket and write

    return Promise.reject({ code: 501, message: 'Not implemented.' });
};

module.exports.copy = function copy( toFind, destination ) {
    // TODO: hit bucket and copy

    return Promise.reject({ code: 501, message: 'Not implemented.' });
};

module.exports.destroy = function destroy( toFind ) {
    // TODO: hit mongo and delete

    return Promise.reject({ code: 501, message: 'Not implemented.' });
};

'use strict';

/* eslint no-unused-vars: 0 */

module.exports.read = function read( toFind ) {
    // TODO: hit bucket and read

    return Promise.reject( 'NOT_IMPLEMENTED' );
};

module.exports.write = function write( toWrite ) {
    // TODO: hit bucket and write

    return Promise.reject( 'NOT_IMPLEMENTED' );
};

module.exports.copy = function copy( toFind, destination ) {
    // TODO: hit bucket and copy

    return Promise.reject( 'NOT_IMPLEMENTED' );
};

module.exports.destroy = function destroy( toFind ) {
    // TODO: hit mongo and delete

    return Promise.reject( 'NOT_IMPLEMENTED' );
};

Fix not implemented return value


/*!
 * jQuery JavaScript Library v@VERSION
 * http://jquery.com/
 *
 * Copyright 2009, John Resig
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://docs.jquery.com/License
 *
 * Includes Sizzle.js
 * http://sizzlejs.com/
 * Copyright 2009, The Dojo Foundation
 * Released under the MIT, BSD, and GPL Licenses.
 *
 * Date:
 */
(function( window, undefined ) {

/*!
 * jQuery JavaScript Library v@VERSION
 * http://jquery.com/
 *
 * Copyright 2010, John Resig
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://docs.jquery.com/License
 *
 * Includes Sizzle.js
 * http://sizzlejs.com/
 * Copyright 2010, The Dojo Foundation
 * Released under the MIT, BSD, and GPL Licenses.
 *
 * Date:
 */
(function( window, undefined ) {

Update the copyright from 2009 to 2010.


var gulp = require('gulp');
var build = require('./../gulp-build');
var rename = require('gulp-rename');
var concat = require('gulp-concat');
var browserify = require('gulp-browserify');
var Transform = require("stream").Transform;
var Rx = require('rx');
var Observable = Rx.Observable;
var fs = require('fs');
var path = require('path');

gulp.task('perf', ['perf-device']);
gulp.task('perf-update', runner);
gulp.task('perf-assemble', ['clean.perf'], assemble);
gulp.task('perf-device', ['perf-assemble'], runner);
gulp.task('perf-browser', ['perf-assemble-browser'], runner);
gulp.task('perf-assemble-browser', ['clean.perf'], browser);
gulp.task('perf-all', ['perf-device', 'perf-browser']);

function assemble() {
    return gulp.
        src(['./performance/testConfig.js']).
        pipe(browserify({
            standalone: 'testConfig'
        })).
        pipe(rename('assembledPerf.js')).
        pipe(gulp.dest('performance/bin'));
}

function browser() {
    return gulp.
        src(['./performance/browser.js']).
        pipe(browserify({
            standalone: 'browser'
        })).
        pipe(rename('browser.js')).
        pipe(gulp.dest('performance/bin'));
}

function runner() {
    return gulp.
        src(['performance/bin/assembledPerf.js', 'performance/device.js']).
        pipe(concat({path: 'device.js'})).
        pipe(gulp.dest('performance/bin'));
}

var gulp = require('gulp');
var build = require('./../gulp-build');
var rename = require('gulp-rename');
var concat = require('gulp-concat');
var browserify = require('browserify');
var Transform = require('stream').Transform;
var Rx = require('rx');
var Observable = Rx.Observable;
var fs = require('fs');
var path = require('path');
var vinyl = require('vinyl-source-stream');

gulp.task('perf', ['perf-device']);
gulp.task('perf-update', runner);
gulp.task('perf-assemble', ['clean.perf'], assemble);
gulp.task('perf-device', ['perf-assemble'], runner);
gulp.task('perf-browser', ['perf-assemble-browser'], runner);
gulp.task('perf-assemble-browser', ['clean.perf'], browser);
gulp.task('perf-all', ['perf-device', 'perf-browser']);

function assemble() {
    return browserify('./performance/testConfig.js', {
            standalone: 'testConfig'
        }).
        bundle().
        pipe(vinyl('assembledPerf.js')).
        pipe(gulp.dest('performance/bin'));
}

function browser() {
    return browserify('./performance/browser.js', {
            standalone: 'browser'
        }).
        bundle().
        pipe(vinyl('browser.js')).
        pipe(gulp.dest('performance/bin'));
}

function runner() {
    return gulp.
        src(['performance/bin/assembledPerf.js', 'performance/device.js']).
        pipe(concat({path: 'device.js'})).
        pipe(gulp.dest('performance/bin'));
}

Update perf scripts to use browserify rather than gulp-browserify.


import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import Logo from './Logo.js';

class Home extends Component {
  render(){
    return (

        <Logo />

Approximately 8.0% of males and 0.5% of females are colorblind: that's about 4.5% of the human population.  One common misconception is that colorblindness can only be inherited; color vision deficiencies can also be acquired later in life as a result of disease, aging, or certain medications.

The most widely used method for detecting and measuring color vision deficiencies is though the Ishihara color test.  Find out now if you are colorblind, and learn what you can do to avoid colorblindness later in life.

        <Link to="/instructions"><button>Take the Test</button></Link>

    );
  }
}

export default Home;

import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import Logo from './Logo.js';

class Home extends Component {
  render(){
    return (

 <Logo />

        <Link to="/instructions"><button>Take the Test</button></Link>

Approximately 8.0% of males and 0.5% of females are color blind- that's about 4.5% of the human population.  One common misconception is that color blindness can only be inherited; color blindness can also be acquired later in life as a result of disease, aging, or certain medications.

The most widely used method for detecting and measuring color vision deficiencies is the Ishihara color test.  Find out now if you are colorblind, and learn what you can do to avoid colorblindness later in life.

    );
  }
}

export default Home;

Change copy and test link placement on homepage


module.exports = function(config) {
  config.set({
    browsers: ['Chrome', 'Firefox'],
    frameworks: ['mocha'],
    reporters: ['mocha'],

    files: ['test/*.js'],

    preprocessors: {
      'test/*.js': ['webpack', 'sourcemap'],
    },

    webpack: {
      devtool: 'inline-source-map',
      module: {
        loaders: [{ test: /\.js$/, exclude: /node_modules/, loader: 'babel' }],
      },
    },

    webpackServer: {
      noInfo: true,
    },
  });
};

module.exports = function(config) {
  config.set({
    browsers: ['Chrome'],
    frameworks: ['mocha'],
    reporters: ['mocha'],

    files: ['test/*.js'],

    preprocessors: {
      'test/*.js': ['webpack', 'sourcemap'],
    },

    webpack: {
      devtool: 'inline-source-map',
      module: {
        loaders: [{ test: /\.js$/, exclude: /node_modules/, loader: 'babel' }],
      },
    },

    webpackServer: {
      noInfo: true,
    },
  });
};

Use Chrome only for browser testing


module.exports = function mkobj(obj, ...props) {
  if (Array.isArray(obj)) {
    props.unshift(obj);

    // eslint-disable-next-line no-param-reassign
    obj = {};
  }

  props.forEach((prop) => {
    if (prop[0]) {
      // eslint-disable-next-line no-param-reassign
      obj[prop[1]] = prop[2];
    }
  });

  return obj;
};

module.exports = function mkobj(obj, ...props) {
  if (arguments.length === 0) return {};

  if (Array.isArray(obj)) {
    props.unshift(obj);

    // eslint-disable-next-line no-param-reassign
    obj = {};
  }

  props.forEach((prop) => {
    if (prop[0]) {
      // eslint-disable-next-line no-param-reassign
      obj[prop[1]] = prop[2];
    }
  });

  return obj;
};

Return empty obj by default


const pgPromise = require('pg-promise')
const pgp = pgPromise()
const db = pgp(`postgres://${process.env.USER}@localhost:5432/hotel_db`)

const listGuests = 'SELECT * FROM guests'
const listAllRooms = "SELECT room_number, capacity, CASE WHEN check_out < '20170831' THEN 'true' WHEN check_out > '20170831' THEN 'false' END AS available FROM rooms JOIN bookings ON rooms.id = bookings.room_id"
const listRoomsAvailable = "SELECT room_number, capacity, 'true' as available FROM rooms JOIN bookings ON rooms.id = bookings.room_id WHERE check_out < '20170831'"

Add sql queries for listing guests, listing all rooms, & list available rooms


/* eslint-disable react/prop-types */
import React from "react"
import { shallowEqual } from "./utils/utils"

export const MobXProviderContext = React.createContext({})

export function Provider({ children, ...stores }) {
    const parentValue = React.useContext(MobXProviderContext)
    const value = React.useRef({
        ...parentValue,
        ...stores
    }).current

    if (process.env.NODE_ENV !== "production") {
        const newValue = { ...value, ...stores } // spread in previous state for the context based stores
        if (!shallowEqual(value, newValue)) {
            throw new Error(
                "MobX Provider: The set of provided stores has changed. See: https://github.com/mobxjs/mobx-react#the-set-of-provided-stores-has-changed-error."
            )
        }
    }

    return <MobXProviderContext.Provider value={value}>{children}</MobXProviderContext.Provider>
}

Provider.displayName = "MobXProvider"

/* eslint-disable react/prop-types */
import React from "react"
import { shallowEqual } from "./utils/utils"

export const MobXProviderContext = React.createContext({})

export function Provider({ children, ...stores }) {
    const parentValue = React.useContext(MobXProviderContext)
    const value = React.useRef({
        ...parentValue,
        ...stores
    }).current

    if (process && typeof process.env !== "undefined" && process.env.NODE_ENV !== "production") {
        const newValue = { ...value, ...stores } // spread in previous state for the context based stores
        if (!shallowEqual(value, newValue)) {
            throw new Error(
                "MobX Provider: The set of provided stores has changed. See: https://github.com/mobxjs/mobx-react#the-set-of-provided-stores-has-changed-error."
            )
        }
    }

    return <MobXProviderContext.Provider value={value}>{children}</MobXProviderContext.Provider>
}

Provider.displayName = "MobXProvider"

Check if process.env is defined


var Colorize = {};

Colorize.red = function(text) {
  return "\033[1;31m" + text + "\033[0m";
}

Colorize.green = function(text) {
  return "\033[1;32m" + text + "\033[0m";
}

Colorize.yellow = function(text) {
  return "\033[1;33m" + text + "\033[0m";
}

Colorize.blue = function(text) {
  return "\033[1;34m" + text + "\033[0m";
}

module.exports = Colorize

Remove Color from Global Scope


import HomeAssistant from '../home-assistant-js/src/index';

const hass = new HomeAssistant();

window.validateAuth = function validateAuth(authToken, rememberAuth) {
  hass.authActions.validate(authToken, {
    rememberAuth,
    useStreaming: hass.localStoragePreferences.useStreaming,
  });
};

window.removeInitMsg = function removeInitMessage() {
  // remove the HTML init message
  const initMsg = document.getElementById('ha-init-skeleton');
  if (initMsg) {
    initMsg.parentElement.removeChild(initMsg);
  }
};

hass.reactor.batch(function () {
  hass.navigationActions.showSidebar(
    hass.localStoragePreferences.showSidebar);

  // if auth was given, tell the backend
  if (window.noAuth) {
    window.validateAuth('', false);
  } else if (hass.localStoragePreferences.authToken) {
    window.validateAuth(hass.localStoragePreferences.authToken, true);
  }
});

setTimeout(hass.startLocalStoragePreferencesSync, 5000);

if ('serviceWorker' in navigator) {
  window.addEventListener('load', function() {
    navigator.serviceWorker.register('/service-worker.js');
  });
}

// While we figure out how ha-entity-marker can keep it's references
window.hass = hass;

import HomeAssistant from '../home-assistant-js/src/index';

const hass = new HomeAssistant();

window.validateAuth = function validateAuth(authToken, rememberAuth) {
  hass.authActions.validate(authToken, {
    rememberAuth,
    useStreaming: hass.localStoragePreferences.useStreaming,
  });
};

window.removeInitMsg = function removeInitMessage() {
  // remove the HTML init message
  const initMsg = document.getElementById('ha-init-skeleton');
  if (initMsg) {
    initMsg.parentElement.removeChild(initMsg);
  }
};

hass.reactor.batch(function () {
  hass.navigationActions.showSidebar(
    hass.localStoragePreferences.showSidebar);

  // if auth was given, tell the backend
  if (window.noAuth) {
    window.validateAuth('', false);
  } else if (hass.localStoragePreferences.authToken) {
    window.validateAuth(hass.localStoragePreferences.authToken, true);
  }
});

setTimeout(hass.startLocalStoragePreferencesSync, 5000);

if ('serviceWorker' in navigator) {
  window.addEventListener('load', function() {
    navigator.serviceWorker.register('/service_worker.js');
  });
}

// While we figure out how ha-entity-marker can keep it's references
window.hass = hass;

Fix url to service worker


'use strict';
var extend = require('xtend');

var common = require('./webpack.common');

module.exports = extend(common, {
    entry: './lib/index',
    externals: {
        react: 'react',
    },
    module: {
        loaders: common.loaders.concat([{
            test: /\.(js|jsx)$/,
            loaders: ['jsx?harmony'],
            exclude: /node_modules/,
        }])
    }
});

'use strict';
var extend = require('xtend');

var common = require('./webpack.common');

module.exports = extend(common, {
    entry: './lib/index',
    externals: {
        react: {
            commonjs: 'react',
            commonjs2: 'react',
            amd: 'React',
            root: 'React'
        }
    },
    module: {
        loaders: common.loaders.concat([{
            test: /\.(js|jsx)$/,
            loaders: ['jsx?harmony'],
            exclude: /node_modules/,
        }])
    }
});

Update externals so that global entry point works in UMD


define([
  'jquery',
  'underscore',
  'backbone',
  'vm',
	'events',
  'text!templates/layout.html'
], function($, _, Backbone, Vm, Events, layoutTemplate){
  var AppView = Backbone.View.extend({
    el: '.kalei',

    render: function () {
			var that = this;
      $(this.el).html(layoutTemplate);
      require(['views/style/menu'], function (StyleMenuView) {
        var styleMenuView = Vm.create(that, 'StyleMenuView', StyleMenuView);
        styleMenuView.render();
      });

		}
	});
  return AppView;
});

define([
  'jquery',
  'underscore',
  'backbone',
  'vm',
	'events',
  'text!templates/layout.html'
], function($, _, Backbone, Vm, Events, layoutTemplate){
  var AppView = Backbone.View.extend({
    el: '.js-kalei',

    render: function () {
			var that = this;
      $(this.el).html(layoutTemplate);
      require(['views/style/menu'], function (StyleMenuView) {
        var styleMenuView = Vm.create(that, 'StyleMenuView', StyleMenuView);
        styleMenuView.render();
      });

		}
	});
  return AppView;
});

Change class to a non-semantic javascript one


  dom = function (els) {
    var _i;

    for (_i = 0; _i < els.length; _i+=1) {
      this[_i] = els[_i];
    }

    this.length = els.length;
  };

  dom = function (els) {
    var _i, _l;

    for (_i = 0, _l = els.length; _i < _l; _i+=1) {
      this[_i] = els[_i];
    }

    this.length = els.length;
  };

  createEl = function (tagName, attrs) {
    var elm = new dom([document.createElement(tagName)]), key;

    if (attrs) {
      if (attrs.className) {
        el.addClass(className);
        delete attrs.className;
      }

      if (attrs.text) {
        el.text(attrs.text);
        delete attrs.text;
      }

      for (key in attrs) {
        if(attrs.hasOwnProperty(key)) {
          el.attr(key, attr['key']);
        }
      }
    }

    return elm;
  };

  hilo.create = createEl;

Add HTMLElement ($.create()) creation feature


import * as THREE from 'three';

function Axes(target, targetCamera) {
  this._target = target;
  this._targetCamera = targetCamera;
  this._camera = new THREE.PerspectiveCamera(targetCamera.fov, targetCamera.aspect, 1, 100);
  this._object = new THREE.AxisHelper(1);
  this._scene = new THREE.Scene();
  this._scene.add(this._object);

  this._update();
}

Axes.prototype._update = function() {
  var fov = this._targetCamera.fov;
  var camera = this._camera;
  camera.aspect = this._targetCamera.aspect;
  camera.setMinimalFov(fov);
  camera.setDistanceToFit(1.0, fov);
  camera.updateProjectionMatrix();

  this._object.quaternion.copy(this._target.quaternion);
};

Axes.prototype.render = function(renderer) {
  this._update();

  var full = renderer.getDrawingBufferSize();
  var width = full.width * 0.25;
  var height = full.height * 0.25;

  var autoClear = renderer.autoClear;
  renderer.autoClear = false;
  renderer.setViewport(0.0, full.height - height, width, height); // use left bottom corner
  renderer.clear(false, true, false);
  renderer.render(this._scene, this._camera);
  renderer.setViewport(0, 0, full.width, full.height);
  renderer.autoClear = autoClear;
};

export default Axes;

import * as THREE from 'three';

function Axes(target, targetCamera) {
  this._target = target;
  this._targetCamera = targetCamera;
  this._camera = new THREE.PerspectiveCamera(targetCamera.fov, targetCamera.aspect, 1, 100);
  this._object = new THREE.AxisHelper(1);
  this._scene = new THREE.Scene();
  this._scene.add(this._object);

  this._update();
}

Axes.prototype._update = function() {
  var fov = this._targetCamera.fov;
  var camera = this._camera;
  camera.aspect = this._targetCamera.aspect;
  camera.setMinimalFov(fov);
  camera.setDistanceToFit(1.0, fov);
  camera.updateProjectionMatrix();

  this._object.quaternion.copy(this._target.quaternion);
};

Axes.prototype.render = function(renderer) {
  this._update();

  var full = renderer.getSize();
  var width = full.width * 0.25;
  var height = full.height * 0.25;

  var autoClear = renderer.autoClear;
  renderer.autoClear = false;
  renderer.setViewport(0.0, full.height - height, width, height); // use left bottom corner
  renderer.clear(false, true, false);
  renderer.render(this._scene, this._camera);
  renderer.setViewport(0, 0, full.width, full.height);
  renderer.autoClear = autoClear;
};

export default Axes;

Fix molecule offset on mobile devices. Use renderer size instead of canvas'


import React from 'react'
import DeleteConfirmButtons from 'shared/components/DeleteConfirmButtons'

const DeleteTableCell = (props) => (
  <td className="text-right" style={{width: "85px"}}>
    <DeleteConfirmButtons {...props} />
  </td>
)

export default DeleteTableCell

import React from 'react'
import DeleteConfirmButtons from 'shared/components/DeleteConfirmButtons'

const DeleteConfirmTableCell = (props) => (
  <td className="text-right" style={{width: "85px"}}>
    <DeleteConfirmButtons {...props} />
  </td>
)

export default DeleteConfirmTableCell

Rename component to follow convention


'use strict';

var through = require('through2');
var stream  = require('stream');
var File    = require('vinyl');

module.exports = new NgStore();

function NgStore() {
    this.store = {};
}

NgStore.prototype.register =
function register(type) {
    if (!this.store[type]) {
        this.store[type] = [];
    }

    var store = this.store[type];

    return through.obj(_register);

    function _register(file, enc, done) {

        var uniqueId = file.data.dirname + '.' + file.data.name;
        if (!store[uniqueId]) {
            store[uniqueId] = file.data;
        }

        //Override if more specific
        if (store[uniqueId].path && store[uniqueId].path.length < file.data.path.length) {
            store[uniqueId] = file.data;
        }

        return done(null, file);
    }
};

NgStore.prototype.stream =
function toStream() {
    var storeStream = new stream.Readable({ objectMode: true });
    var store       = this.store;
    var contents    = {};
    var type;

    for (type in store) {
        contents[type] = Object.keys(store[type]).map(function(path) {
            return store[type][path];
        });
    }

    storeStream._read = Function.prototype;
    storeStream.push(new File({
        contents: new Buffer(JSON.stringify(contents))
    }));
    storeStream.push(null);

    return storeStream;
};

'use strict';

var through = require('through2');
var stream  = require('stream');
var File    = require('vinyl');

module.exports = new NgStore();

function NgStore() {
    this.store = {};
}

NgStore.prototype.register =
function register(type) {
    if (!this.store[type]) {
        this.store[type] = [];
    }

    var store = this.store[type];

    return through.obj(_register);

    function _register(file, enc, done) {

        var uniqueId = file.data.dirname + '.' + file.data.name;
        if (!store[uniqueId]) {
            store[uniqueId] = file.data;
        }

        //Override if more specific
        if (store[uniqueId].path.length < file.data.path.length) {
            store[uniqueId] = file.data;
        }

        return done(null, file);
    }
};

NgStore.prototype.stream =
function toStream() {
    var storeStream = new stream.Readable({ objectMode: true });
    var store       = this.store;
    var contents    = {};
    var type;

    for (type in store) {
        contents[type] = Object.keys(store[type]).map(function(path) {
            return store[type][path];
        });
    }

    storeStream._read = Function.prototype;
    storeStream.push(new File({
        contents: new Buffer(JSON.stringify(contents))
    }));
    storeStream.push(null);

    return storeStream;
};

Revert "Ensure store[uniqueId].path is defined"


var fs = require('fs');
var path = require('path');
var csso = require('csso');
var autoprefixer = require('autoprefixer');
var UglifyJS = require('uglify-js');

var inlineCSS = function(cssPath) {
    var css = fs.readFileSync(path.join(__dirname, cssPath), 'utf-8');
    css = csso.justDoIt(css, false);
    css = autoprefixer.process(css).css;
    return css;
};

var inlineJS = function(jsPath) {
    var result = UglifyJS.minify(path.join(__dirname, jsPath));
    return result.code;
};

module.exports = {
    opensans: inlineCSS('../assets/styles/opensans.css'),
    icomoon: inlineCSS('../assets/styles/icomoon.css'),
    bootstrap: inlineCSS('../assets/styles/bootstrap.min.css'),
    global: inlineCSS('../assets/styles/global.css'),
    profile: inlineCSS('../assets/styles/profile.css'),
    style: inlineCSS('../assets/styles/style.css'),
    saveAs: inlineJS('../node_modules/browser-saveas/index.js'),
    smoothScroll: inlineJS('../node_modules/smooth-scroll/dist/js/smooth-scroll.min.js'),
    emailScramble: inlineJS('../node_modules/email-scramble/email-scramble.js'),
    script: inlineJS('../assets/scripts/script.js')
};

var fs = require('fs');
var path = require('path');
var csso = require('csso');
var autoprefixer = require('autoprefixer');
var UglifyJS = require('uglify-js');

var inlineCSS = function(cssPath) {
    var css = fs.readFileSync(path.join(__dirname, cssPath), 'utf-8');
    css = csso.minify(css, false);
    css = autoprefixer.process(css).css;
    return css;
};

var inlineJS = function(jsPath) {
    var result = UglifyJS.minify(path.join(__dirname, jsPath));
    return result.code;
};

module.exports = {
    opensans: inlineCSS('../assets/styles/opensans.css'),
    icomoon: inlineCSS('../assets/styles/icomoon.css'),
    bootstrap: inlineCSS('../assets/styles/bootstrap.min.css'),
    global: inlineCSS('../assets/styles/global.css'),
    profile: inlineCSS('../assets/styles/profile.css'),
    style: inlineCSS('../assets/styles/style.css'),
    saveAs: inlineJS('../node_modules/browser-saveas/index.js'),
    smoothScroll: inlineJS('../node_modules/smooth-scroll/dist/js/smooth-scroll.min.js'),
    emailScramble: inlineJS('../node_modules/email-scramble/email-scramble.js'),
    script: inlineJS('../assets/scripts/script.js')
};

Switch from csso justDoIt to minify because of deprecation notice


var debug = require('debug')('nds');

function Resolver() {
  this._mechs = [];
}

Resolver.prototype.use = function(fn) {
  this._mechs.push(fn);
};

Resolver.prototype.query = function(id, issuer, cb) {
  var self = this
    , stack = this._mechs
    , idx = 0;

  debug('id %s %s', id, issuer);

  function next(err, entity) {
    if (err || entity) { return cb(err, entity); }

    var layer = stack[idx++];
    if (!layer) { return cb(new Error('Failed to resolve identifier "' + id + '"')); }

    try {
      debug('resolve %s', layer.name || 'anonymous');
      var arity = layer.length;
      if (arity == 3) { // async
        layer(id, issuer, next);
      } else {
        // TODO: Ensure that issuer is undefined or equal to id
        layer(id, next);
      }
    } catch (ex) {
      next(ex);
    }
  }
  next();
};

module.exports = Resolver;

var debug = require('debug')('nds');

function Resolver() {
  this._mechs = [];
}

Resolver.prototype.use = function(fn) {
  this._mechs.push(fn);
};

Resolver.prototype.query = function(id, issuer, cb) {
  if (typeof issuer == 'function') {
    cb = issuer;
    issuer = undefined;
  }

  var self = this
    , stack = this._mechs
    , idx = 0;

  debug('id %s %s', id, issuer);

  function next(err, entity) {
    if (err || entity) { return cb(err, entity); }

    var layer = stack[idx++];
    if (!layer) { return cb(new Error('Failed to resolve identifier "' + id + '"')); }

    try {
      debug('resolve %s', layer.name || 'anonymous');
      var arity = layer.length;
      if (arity == 3) { // async
        layer(id, issuer, next);
      } else {
        // TODO: Ensure that issuer is undefined or equal to id
        layer(id, next);
      }
    } catch (ex) {
      next(ex);
    }
  }
  next();
};

module.exports = Resolver;

Allow only id argument to be passed.


// finds and sets textareas to use monospaced font
var monospaceTextareas = function() {
  var textareas = document.getElementsByTagName("textarea");

  for (i = 0; i < textareas.length; i++) {
      textareas[i].style.fontFamily = "monospace";
  }
}

// sets MutationObserver to look for dynamic textareas in the body of html
var setMutationObserver = function() {
  // select the target node for mutation observer
  var target = document.body;

  // create an observer instance
  var observer = new MutationObserver(function(mutations) {
    monospaceTextareas();
  });

  // configuration of the observer:
  var config = { attributes: true, childList: true, subtree: true, characterData: true };

  // pass in the target node, as well as the observer options
  observer.observe(target, config);
}

// set textareas to be monospaced on page load
// and then set the mutation observer
monospaceTextareas();
setMutationObserver();

Add mutation observer to catch changes in the DOM


/**
 *
 * LeftMenuFooter
 *
 */

import React from 'react';
import { PropTypes } from 'prop-types';
import Wrapper, { A } from './Wrapper';

function LeftMenuFooter({ version }) {
  // PROJECT_TYPE is an env variable defined in the webpack config
  // eslint-disable-next-line no-undef
  const projectType = PROJECT_TYPE;

  return (
    <Wrapper>

          Strapi

        <A
          href={`https://github.com/strapi/strapi/releases/tag/v${version}`}
          key="github"
          target="_blank"
          rel="noopener noreferrer"
        >
          v{version}

          — {projectType} Edition

    </Wrapper>
  );
}

LeftMenuFooter.propTypes = {
  version: PropTypes.string.isRequired,
};

export default LeftMenuFooter;

Fix hover state strapi link


import React from 'react';

class CardStackPanResponder {
}

class PagerPanResponder {
}

class NavigationCard extends React.Component {
}

NavigationCard.CardStackPanResponder = CardStackPanResponder;
NavigationCard.CardStackStyleInterpolator = {
  forHorizontal: () => ({}),
  forVertical: () => ({}),
};
NavigationCard.PagerPanResponder = PagerPanResponder;
NavigationCard.PagerStyleInterpolator = {
  forHorizontal: () => ({}),
};

module.exports = NavigationCard;

class CardStackPanResponder {
}

class PagerPanResponder {
}

const NavigationCard = (props) => null;

NavigationCard.CardStackPanResponder = CardStackPanResponder;
NavigationCard.CardStackStyleInterpolator = {
  forHorizontal: () => ({}),
  forVertical: () => ({}),
};
NavigationCard.PagerPanResponder = PagerPanResponder;
NavigationCard.PagerStyleInterpolator = {
  forHorizontal: () => ({}),
};

module.exports = NavigationCard;

Write as stateless function for linter


var gulp = require('gulp');

var embedDefs = [
  {
    componentPath: 'src/js/components/hello-world.jsx',
    path: '/hello-world'
  },
  {
    componentPath: 'src/js/components/hello-world-two.jsx',
    path: '/hello-world-two'
  }
];

var opts = {
  embedDefs: embedDefs,
  paths: ['node_modules/lucify-commons', 'test_modules/module1'],
  publishFromFolder: 'dist',
  defaultBucket: 'lucify-dev',
  maxAge: 3600,
  assetContext: 'embed/',
  baseUrl: 'http://dev.lucify.com/'
};

var builder = require('../../index.js'); // lucify-component-builder
builder(gulp, opts);

var gulp = require('gulp');

var embedDefs = [
  {
    componentPath: 'src/js/components/hello-world.jsx',
    path: '/hello-world'
  },
  {
    componentPath: 'src/js/components/hello-world-two.jsx',
    path: '/subpath/hello-world-two'
  }
];

var opts = {
  embedDefs: embedDefs,
  paths: ['node_modules/lucify-commons', 'test_modules/module1'],
  publishFromFolder: 'dist',
  defaultBucket: 'lucify-dev',
  maxAge: 3600,
  assetContext: 'embed/',
  baseUrl: 'http://dev.lucify.com/'
};

var builder = require('../../index.js'); // lucify-component-builder
builder(gulp, opts);

Make the multi-embed-test-project use a complex subpath for 2nd component


var util = require('util');

var Jscs = require('jscs');

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

var Validator = function() {
};

util.inherits(Validator, DefaultValidator);

Validator.prototype.validate = function(options, cb) {
	var jscs = new Jscs();
	jscs.registerDefaultRules();
	var conf = {};
	for (var key in options.config) conf[key] = options.config[key];
	jscs.configure(conf);
	try {
		var errors = jscs.checkString(options.content, options.path);
		errors = errors.getErrorList();
		cb(null, errors);
	} catch (e) {
		cb([e], []);
	}
};

module.exports = Validator;

var util = require('util');

var Jscs = require('jscs');

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

var Validator = function() {
};

util.inherits(Validator, DefaultValidator);

Validator.prototype.validate = function(options, cb) {
	var jscs = new Jscs();
	jscs.registerDefaultRules();
	var conf = {};
	for (var key in options.config) conf[key] = options.config[key];
	jscs.configure(conf);
	try {
		var errors = jscs.checkString(options.content, options.path);
		errors = errors.getErrorList().map(function(error) {
			return {
				line: error.line,
				column: error.column,
				message: error.message,
				code: 'jscs'
			};
		});
		cb(null, errors);
	} catch (e) {
		cb([e], []);
	}
};

module.exports = Validator;

Add code to jscs lint errors


'use strict'

import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import App from './containers/app/index'
import configureStore from './store/configure-store'
import reducers from './reducers/index'

const store = configureStore({ reducers })

render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.querySelector('[data-js="app"]')
)

store.subscribe(() => {
  console.log(store.getState())
})

Add subscribe to change redux events