/**
 * Created by Julian/Wolke on 27.11.2016.
 */
let Manager = require('../../structures/manager');
let Cleverbot = require('cleverbot');

let re = /<@[0-9].*>/g;
let cleverbotKey = remConfig.cleverbot_api_key;

class CleverBotManager extends Manager {
    constructor() {
        super();
        this.cleverbot = new Cleverbot({'key': cleverbotKey});
        this.continuationStrings = {};
    }

    talk(msg) {
        var message = msg.content.replace(re, '');
        var continuationString = this.continuationStrings[msg.channel.id];

        if (continuationString && continuationString.length > 2000) {
            msg.channel.createMessage("I am having trouble remembering this conversation... Let's start over!");
            this.continuationStrings[msg.channel.id] = undefined;
            return;
        }

        this.cleverbot
            .query(message, {'cs': continuationString})
            .then(response => {
                msg.channel.createMessage(':pencil: ' + response.output);
                this.continuationStrings[msg.channel.id] = response.cs;
            })
            .catch(error => {
                console.error(error);
                return msg.channel.createMessage(':x: An error with cleverbot occured!');
            });
    }
}

module.exports = {class: CleverBotManager, deps: [], async: false, shortcode: 'cm'};

/**
 * Created by Julian/Wolke on 27.11.2016.
 */
let Manager = require('../../structures/manager');
let Cleverbot = require('cleverbot');

let re = /<@[0-9].*>/g;
let cleverbotKey = remConfig.cleverbot_api_key;

class CleverBotManager extends Manager {
    constructor() {
        super();
        this.cleverbot = new Cleverbot({'key': cleverbotKey});
        this.continuationStrings = {};
    }

    talk(msg) {
        var message = msg.content.replace(re, '');
        var continuationString = this.continuationStrings[msg.channel.id];

        if (continuationString && continuationString.length > 2000) {
            msg.channel.createMessage("I am having trouble remembering this conversation... Let's start over!");
            this.continuationStrings[msg.channel.id] = undefined;
            return;
        }

        this.cleverbot
            .query(message, {'cs': continuationString})
            .then(response => {
                setTimeout(() => {
                    msg.channel.sendTyping();
                    setTimeout(() => {
                        msg.channel.createMessage(response.output);
                    }, response.output.length * 65);
                }, message.length * 25);
                this.continuationStrings[msg.channel.id] = response.cs;
            })
            .catch(error => {
                console.error(error);
                return msg.channel.createMessage(':x: An error with cleverbot occured!');
            });
    }
}

module.exports = {class: CleverBotManager, deps: [], async: false, shortcode: 'cm'};

Make cleverbot module behave like a typing human


import React, { PureComponent } from 'react';

import utils  from '../../utils/utils';

/*
|--------------------------------------------------------------------------
| Header - PlayingBar
|--------------------------------------------------------------------------
*/

export default class TrackCover extends PureComponent {

    static propTypes = {
        path: React.PropTypes.string,
    }

    constructor(props) {
        super(props);
        this.state = {
            coverPath: null,
        };

        this.fetchInitialCover = this.fetchInitialCover.bind(this);
    }

    render() {
        if(this.state.coverPath) {
            const styles = { backgroundImage: `url('${this.state.coverPath}')` };

            return
;
        }

        return(

♪

        );
    }

    componentDidMount() {
        this.fetchInitialCover();
    }

    async componentWillUpdate(nextProps) {
        if(nextProps.path !== this.props.path) {
            const coverPath = await utils.fetchCover(nextProps.path);
            this.setState({ coverPath });
        }
    }

    async fetchInitialCover() {
        const coverPath = await utils.fetchCover(this.props.path);
        this.setState({ coverPath });
    }
}

import React, { PureComponent } from 'react';

import utils  from '../../utils/utils';

/*
|--------------------------------------------------------------------------
| Header - PlayingBar
|--------------------------------------------------------------------------
*/

export default class TrackCover extends PureComponent {

    static propTypes = {
        path: React.PropTypes.string,
    }

    constructor(props) {
        super(props);
        this.state = {
            coverPath: null,
        };

        this.fetchInitialCover = this.fetchInitialCover.bind(this);
    }

    render() {
        if(this.state.coverPath) {
            const coverPath = encodeURI(this.state.coverPath)
                .replace(/'/g, '\\\'')
                .replace(/"/g, '\\"');
            const styles = { backgroundImage: `url('${coverPath}')` };

            return
;
        }

        return(

♪

        );
    }

    componentDidMount() {
        this.fetchInitialCover();
    }

    async componentWillUpdate(nextProps) {
        if(nextProps.path !== this.props.path) {
            const coverPath = await utils.fetchCover(nextProps.path);
            this.setState({ coverPath });
        }
    }

    async fetchInitialCover() {
        const coverPath = await utils.fetchCover(this.props.path);
        this.setState({ coverPath });
    }
}

Fix cover fetch when it has single or doublequotes in its path


require('../sass/main.scss');
import 'babel-polyfill';
import NamesPanel from './names-panel.js';
import OptionsPanel from './options-panel.js';

new NamesPanel().init();
new OptionsPanel().init();

require('../sass/main.scss');
import NamesPanel from './names-panel.js';
import OptionsPanel from './options-panel.js';

new NamesPanel().init();
new OptionsPanel().init();

Use Babel polyfill from browser only


module.exports = {
  "browsersync": {
    "files": [
      "./app/assets/_compiled/styles.css",
      "./app/assets/_compiled/*.js",
      "./app/templates/**/*.html"
    ],
    "server": "app",
    "notify": false,
    "open": false
  },
  "templatePath": "/*.html" // Relative to the app directory
}

const templatePath = "/templates/**/*.html";

module.exports = {
  "browsersync": {
    "files": [
      "./app/assets/_compiled/styles.css",
      "./app/assets/_compiled/*.js",
      "./app" + templatePath
    ],
    "proxy": "", // use this if it's NOT a static site, ex: app.trendyminds.dev
    // "server": "app" // use this if it IS a static site
    "notify": false,
    "open": true
  },
  "templatePath": templatePath // Relative to the app directory
}

Change template path to a const; Add proxy option and comments.


const qs = require('qs');

module.exports.handler = (event, context, callback) => {
  /** Immediate response for WarmUP plugin */
  if (event.source === 'serverless-plugin-warmup') {
    console.log('WarmUP - Lambda is warm!');
    return callback(null, 'Lambda is warm!');
  }

  const body = qs.parse(event.body);
  const result = body.text === 'coin'
    ? `:coin_${Math.floor((Math.random() * 2) + 1)}:`
    : `:dice_${Math.floor((Math.random() * 6) + 1)}:`;
  const response = {
    statusCode: 200,
    headers: {
      // Required for CORS support to work
      'Access-Control-Allow-Origin': '*',

      // Required for cookies, authorization headers with HTTPS
      'Access-Control-Allow-Credentials': true,
      'Content-type': 'application/json',
    },
    body: JSON.stringify({
      response_type: 'in_channel',
      text: `@${body.user_name} just rolled: ${result}`,
    }),
  };

  callback(null, response);
};

const qs = require('qs');

module.exports.handler = (event, context, callback) => {
  /** Immediate response for WarmUP plugin */
  if (event.source === 'serverless-plugin-warmup') {
    console.log('WarmUP - Lambda is warm!');
    return callback(null, 'Lambda is warm!');
  }

  const body = qs.parse(event.body);
  const result = body.text === 'coin'
    ? `:coin_${Math.floor((Math.random() * 2) + 1)}:`
    : `:dice_${Math.floor((Math.random() * 6) + 1)}:`;
  const response = {
    statusCode: 200,
    headers: {
      // Required for CORS support to work
      'Access-Control-Allow-Origin': '*',

      // Required for cookies, authorization headers with HTTPS
      'Access-Control-Allow-Credentials': true,
      'Content-type': 'application/json',
    },
    body: JSON.stringify({
      response_type: 'in_channel',
      text: `@${body.user_name || 'You'} just rolled: ${result}`,
    }),
  };

  callback(null, response);
};

Set default user name to 'You'.


window.AudioContext = window.AudioContext || window.webkitAudioContext;
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
navigator.cancelAnimationFrame = navigator.cancelAnimationFrame || navigator.webkitCancelAnimationFrame || navigator.mozCancelAnimationFrame;
navigator.requestAnimationFrame = navigator.requestAnimationFrame || navigator.webkitRequestAnimationFrame || navigator.mozRequestAnimationFrame;

var audioCtx = new AudioContext();

var analyser = audioCtx.createAnalyser();

var distortion = audioCtx.createWaveShaper();
var gainNode = audioCtx.createGain();
var biquadFiler = audioCtx.createBiquadFilter();
var convolver = audioCtx.createConvolver();

if (!navigator.getUserMedia) {
	throw new Error("getUserMedia not supported");
}

navigator.getUserMedia(
	{
		audio: true,
		video: true
	},
	function (stream) {
		document.getElementById('camFeed').src = window.URL.createObjectURL(stream);
	},
	function (err) {
		console.log("The following error occured: " + err.name);
	}
);

window.AudioContext = window.AudioContext || window.webkitAudioContext;
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
navigator.cancelAnimationFrame = navigator.cancelAnimationFrame || navigator.webkitCancelAnimationFrame || navigator.mozCancelAnimationFrame;
navigator.requestAnimationFrame = navigator.requestAnimationFrame || navigator.webkitRequestAnimationFrame || navigator.mozRequestAnimationFrame;

var audioCtx = new AudioContext();

var analyser = audioCtx.createAnalyser();

var distortion = audioCtx.createWaveShaper();
var gainNode = audioCtx.createGain();
var biquadFiler = audioCtx.createBiquadFilter();
var convolver = audioCtx.createConvolver();

if (!navigator.getUserMedia) {
	throw new Error("getUserMedia not supported");
}

navigator.getUserMedia(
	{
		audio: true,
		video: true
	},
	function (stream) {
		document.querySelector('#camFeed').src = window.URL.createObjectURL(stream);
	},
	function (err) {
		console.log("The following error occured: " + err.name);
	}
);

Use querySelector instead of getElementById.


// 36: Symbol.keyFor - retrieves a shared symbol key from the global symbol registry
// To do: make all tests pass, leave the assert lines unchanged!

describe('`Symbol.keyFor` gets the symbol key for a given symbol', function() {

  it('pass the symbol to `keyFor()` and you get it`s key', function() {
    const sym = Symbol.for('foo');
    const key = Symbol.keyFor(sym);

    assert.equal(key, 'foo');
  });

  it('local symbols are not in the runtime-wide registry', function() {
    const localSymbol = Symbol('foo');
    const key = Symbol.keyFor(localSymbol);

    assert.equal(key, void 0);
  });

  it('well-known symbols are not in the runtime-wide registry either', function() {
    const key = Symbol.keyFor(Symbol.iterator);

    assert.equal(key, void 0);
  });

  it('for non-Symbols throws an error', function() {
    function fn() {
      Symbol.keyFor(null);
    }

    assert.throws(fn);
  });

});

// 36: Symbol.keyFor - retrieves a shared symbol key from the global symbol registry
// To do: make all tests pass, leave the assert lines unchanged!

describe('`Symbol.keyFor` gets the symbol key for a given symbol', function() {

  const sym = Symbol.for('foo');

  it('pass the symbol to `keyFor()` and you get it`s key', function() {
    const key = Symbol.____(sym);

    assert.equal(key, 'foo');
  });

  it('local symbols are not in the runtime-wide registry', function() {
    // hint: `Symbol()` creates a local symbol!
    const localSymbol = Symbol.for('foo');
    const key = Symbol.keyFor(localSymbol);

    assert.equal(key, void 0);
  });

  it('well-known symbols are not in the runtime-wide registry either', function() {
    const key = Symbol.keyFor(Symbol.iteraTor);

    assert.equal(key, void 0);
  });

  it('for non-Symbols throws an error', function() {
    function fn() {
      Symbol.keyFor(sym);
    }

    assert.throws(fn);
  });

});

Make it a kata, all tests fail.


describe('pingPong', function() {
  it("returns ping for a number that is divisible by 3", function() {
    expect(pingPong(6)).to.equal("ping");
  });
  it("returns pong for a number that is divisible by 5", function() {
    expect(pingPong(10)).to.equal("pong");
  });
  it("returns ping pong for a number that is divisible by 3 and 5", function() {
    expect(pingPong(30)).to.equal("ping pong")
  });
  it("is false for a number that is not divisible by 3 or 5", function() {
    expect(pingPong(8)).to.equal(false);
  });
});

describe('pingPong', function() {
  it("returns true for a number that is divisible by 3", function() {
    expect(pingPong(6)).to.equal(true);
  });
  it("returns true for a number that is divisible by 5", function() {
    expect(pingPong(10)).to.equal(true);
  });
  it("returns true for a number that is divisible by 3 and 5", function() {
    expect(pingPong(30)).to.equal(true)
  });
  it("is false for a number that is not divisible by 3 or 5", function() {
    expect(pingPong(8)).to.equal(false);
  });
});

Revert spec test back to true/false


exports.handler = async (event, context) => {
  console.log('Snipcart webhook received!');
  console.log('event', event);
  console.log('context', context);
  return {
    statusCode: 200,
    body: 'Thanks for the webhook snipcart!'
  };
};

const https = require('https');

console.log('Snipcart webhook received!');

const method = 'POST';
const host = 'api.netlify.com';
const path =
  '/build_hooks/5ef219aec0c4ea9331e5fe67?trigger_branch=master&trigger_title=Triggered+by+Netlify+Functions+via+Snipcart+webhook';
const options = {
  method,
  host,
  path
};

exports.handler = async (event) => {
  const body = event.body;

  if (body.eventName && body.eventName === 'order.completed') {
    console.log('ORDER UP 🎉');

    const post = https.request(options, (res) => {
      console.log(`POST response status: ${res.statusCode}`);
    });

    post.on('error', (e) => {
      console.error(`Problem with POST: ${e.message}`);
    });

    post.end();
  }

  return {
    statusCode: 200,
    body: 'Thanks for the webhook snipcart!'
  };
};

Send conditional POST req to netlify build hook


'use strict';

var Assert      = require('test/assert').Assert
  , bindMethods = require('es5-ext/lib/Object/bind-methods')

  , never, neverBind;

never = function (message) {
	this.fail({
		message: message,
		operator: "never"
	});
};

neverBind = function (message) {
	return never.bind(this, message);
};

module.exports = function (logger) {

	var assert = new Assert({
		pass:  logger.pass.bind(logger),
		fail:  logger.fail.bind(logger),
		error: logger.error.bind(logger)
	});

	assert = bindMethods(assert.strictEqual.bind(assert),
		assert, Assert.prototype);

	assert.not       = assert.notStrictEqual;
	assert.deep      = assert.deepEqual;
	assert.notDeep   = assert.notDeepEqual;
	assert.never     = never.bind(assert);
	assert.never.bind = neverBind.bind(assert);

	return assert;
};

'use strict';

var extend = require('es5-ext/lib/Object/extend')
  , map    = require('es5-ext/lib/Object/map')
  , Assert = require('test/assert').Assert

  , never, neverBind;

never = function (message) {
	this.fail({
		message: message,
		operator: "never"
	});
};

neverBind = function (message) {
	return never.bind(this, message);
};

module.exports = function (logger) {

	var assert = new Assert({
		pass:  logger.pass.bind(logger),
		fail:  logger.fail.bind(logger),
		error: logger.error.bind(logger)
	});

	assert = extend(assert.strictEqual.bind(assert),
		map(Assert.prototype, function (method) { return method.bind(assert); }));

	assert.not       = assert.notStrictEqual;
	assert.deep      = assert.deepEqual;
	assert.notDeep   = assert.notDeepEqual;
	assert.never     = never.bind(assert);
	assert.never.bind = neverBind.bind(assert);

	return assert;
};

Update up to changes in es5-ext package


/* -*- coding: utf-8 -*- */
/* global cforum, Highcharts, t */

cforum.admin.jobs = {
  jobsCount: null,
  index: function() {
    Highcharts.setOptions({
      lang: t('highcharts')
    });

    var keys = cforum.admin.jobs.jobsCount.sort(function(a,b) {
      var a_date = new Date(a.day);
      var b_date = new Date(b.day);
      return b_date.getTime() - a_date.getTime();
    });

    $("#chart").highcharts({
      chart: { type: 'spline' },
      title: null,
      xAxis: {
        categories: $.map(keys,
                          function(val, i) {
                            return Highcharts.dateFormat("%A, %d. %B %Y",
                                                         new Date(val.day));
                          })
      },
      yAxis: { title: { text: t('highcharts.cnt_jobs') } },
      series: [{
        name: t('highcharts.jobs'),
        data: $.map(keys, function(val, i) { return val.cnt; })
      }]
    });
  }
};

/* eof */

/* -*- coding: utf-8 -*- */
/* global cforum, Highcharts, t */

cforum.admin.jobs = {
  jobsCount: null,
  index: function() {
    Highcharts.setOptions({
      lang: t('highcharts')
    });

    var keys = cforum.admin.jobs.jobsCount.sort(function(a,b) {
      var a_date = new Date(a.day);
      var b_date = new Date(b.day);
      return a_date.getTime() - b_date.getTime();
    });

    $("#chart").highcharts({
      chart: { type: 'spline' },
      title: null,
      xAxis: {
        categories: $.map(keys,
                          function(val, i) {
                            return Highcharts.dateFormat("%A, %d. %B %Y",
                                                         new Date(val.day));
                          })
      },
      yAxis: { title: { text: t('highcharts.cnt_jobs') } },
      series: [{
        name: t('highcharts.jobs'),
        data: $.map(keys, function(val, i) { return val.cnt; })
      }]
    });
  }
};

/* eof */

Revert "fix: wah, typo - correct order for subtraction"


gemini.suite('CSS component', (suite) => {
  suite.setUrl('/')
    .setCaptureElements('#storybook-preview-iframe')
    .capture('plain');
});

gemini.suite('CSS component', (suite) => {
  suite.setUrl('/?selectedKind=CSS%20component&selectedStory=default')
    .setCaptureElements('#storybook-preview-iframe')
    .capture('plain');
});

gemini.suite('Stateless functional component', (suite) => {
  suite.setUrl('/?selectedKind=Stateless%20functional%20component&selectedStory=default')
    .setCaptureElements('#storybook-preview-iframe')
    .capture('plain');
});

gemini.suite('Web Component', (suite) => {
  suite.setUrl('/?selectedKind=Web%20component&selectedStory=default')
    .setCaptureElements('#storybook-preview-iframe')
    .capture('plain');
});

Add stateless functional component and web component stories


const compiler = require('idyll-compiler')
const fs = require('fs')
const { join } = require('path')

fs.writeFileSync(
  join(__dirname, 'ast.json'),
  JSON.stringify(
    compiler(fs.readFileSync(join(__dirname, 'src.idl'), 'utf8')),
    null,
    2
  ),
  'utf8'
)

const compiler = require('idyll-compiler')
const fs = require('fs')
const { join } = require('path')
const { splitAST, translate } = require('./index')

fs.writeFileSync(
  join(__dirname, 'ast.json'),
  JSON.stringify(
    compiler(fs.readFileSync(join(__dirname, 'src.idl'), 'utf8')),
    null,
    2
  ),
  'utf8'
)

fs.writeFileSync(
  join(__dirname, 'schema.json'),
  JSON.stringify(
    translate(
      splitAST(
        JSON.parse(fs.readFileSync(join(__dirname, 'ast.json'), 'utf8'))
      ).elements
    ),
    null,
    2
  ),
  'utf8'
)

Add AST to schema step in util


'use strict';

import Fabric from '../';

const assert = require('assert');
const expect = require('chai').expect;

describe('CLI', function () {
  it('should expose a constructor', function () {
    assert.equal(typeof Fabric.CLI, 'function');
  });

  it('should create an CLI smoothly', async function () {
    let cli = new Fabric.CLI();

    try {
      await cli.start();
      await cli.stop();
      assert.ok(cli);
    } catch (E) {
      console.error(E);
    }
  });
});

'use strict';

import Fabric from '../';

const assert = require('assert');
const expect = require('chai').expect;

describe('CLI', function () {
  it('should expose a constructor', function () {
    assert.equal(typeof Fabric.CLI, 'function');
  });

  it('should create an CLI smoothly', async function () {
    let cli = new Fabric.CLI();

    try {
      await cli.start();
      await cli.stop();
      assert.ok(cli);
    } catch (E) {
      await cli.stop();
      console.error(E);
    }
  });
});

Update CLI test to reliably stop


import {
  weatherIcon
} from 'ember-cli-weather-icons/helpers/weather-icon';

module('WeatherIconHelper');

// Replace this with your real tests.
test('it works', function() {
  var result = weatherIcon('sunny');
  equal(result.toString(), '<i class="wi wi-sunny"></i>');
});

import {
  weatherIcon
} from 'ember-cli-weather-icons/helpers/weather-icon';

module('WeatherIconHelper');

test('it returns an icon with the correct sunny class', function() {
  var result = weatherIcon('sunny');
  equal(result.toString(), '');
});

test('it returns an icon with the correct moon-full class', function() {
  var result = weatherIcon('moon-full');
  equal(result.toString(), '');
});

Add a few more tests


var gData;

function init() {
	if ( !window.arguments) window.close();
	gData = window.arguments[0];
	document.getElementById('sbSourcePreTag').value = gData.preTag;
	document.getElementById('sbSourcePreContext').value = gData.preContext;
	document.getElementById('sbSourceValue').value = gData.value;
	document.getElementById('sbSourcePostContext').value = gData.postContext;
	document.getElementById('sbSourcePostTag').value = gData.postTag;
	document.getElementById('sbSourceValue').select();
}

function accept() {
	gData.preContext = document.getElementById('sbSourcePreContext').value;
	gData.value = document.getElementById('sbSourceValue').value;
	gData.postContext = document.getElementById('sbSourcePostContext').value;
	gData.result = 1;
}

var gData;

function init() {
	if ( !window.arguments) window.close();
	gData = window.arguments[0];
	document.getElementById('sbSourcePreTag').value = gData.preTag;
	document.getElementById('sbSourcePreContext').value = gData.preContext;
	document.getElementById('sbSourceValue').value = gData.value;
	document.getElementById('sbSourcePostContext').value = gData.postContext;
	document.getElementById('sbSourcePostTag').value = gData.postTag;

	if (!gData.preTag) document.getElementById('sbSourcePreTag').hidden = true;
	if (!gData.preContext) document.getElementById('sbSourcePreContext').hidden = true;
	if (!gData.postContext) document.getElementById('sbSourcePostContext').hidden = true;
	if (!gData.postTag) document.getElementById('sbSourcePostTag').hidden = true;

	document.getElementById('sbSourceValue').select();
}

function accept() {
	gData.preContext = document.getElementById('sbSourcePreContext').value;
	gData.value = document.getElementById('sbSourceValue').value;
	gData.postContext = document.getElementById('sbSourcePostContext').value;
	gData.result = 1;
}

Hide context boxes if they are not needed.


'use strict';

/**
* Typed array constructor which returns a typed array representing an array of twos-complement 32-bit signed integers in the platform byte order.
*
* @module @stdlib/array/int32
*
* @example
* var ctor = require( '@stdlib/array/int32' );
*
* var arr = new ctor( 10 );
* // returns <Int32Array>
*/

// MODULES //

var hasInt32ArraySupport = require( '@stdlib/utils/detect-int32array-support' );

// MAIN //

var ctor;
if ( hasInt32ArraySupport() ) {
	ctor = require( './int32array.js' );
} else {
	ctor = require( './polyfill.js' );
}

// EXPORTS //

module.exports = ctor;

'use strict';

/**
* Typed array constructor which returns a typed array representing an array of twos-complement 32-bit signed integers in the platform byte order.
*
* @module @stdlib/array/int32
*
* @example
* var ctor = require( '@stdlib/array/int32' );
*
* var arr = new ctor( 10 );
* // returns <Int32Array>
*/

// MODULES //

var hasInt32ArraySupport = require( '@stdlib/utils/detect-int32array-support' );
var builtin = require( './int32array.js' );
var polyfill = require( './polyfill.js' );

// MAIN //

var ctor;
if ( hasInt32ArraySupport() ) {
	ctor = builtin;
} else {
	ctor = polyfill;
}

// EXPORTS //

module.exports = ctor;

Refactor to avoid dynamic module resolution


'use strict';

function ProxyServerAddon(project) {
  this.project = project;
  this.name = 'proxy-server-middleware';
}

ProxyServerAddon.prototype.serverMiddleware = function(options) {
  var app = options.app, server = options.options.httpServer;
  options = options.options;

  if (options.proxy) {
    var proxy = require('http-proxy').createProxyServer({
      target: options.proxy,
      ws: true,
      secure: !options.insecureProxy,
      changeOrigin: true
    });

    proxy.on('error', function (e) {
      options.ui.writeLine('Error proxying to ' + options.proxy);
      options.ui.writeError(e);
    });

    var morgan = require('morgan');

    options.ui.writeLine('Proxying to ' + options.proxy);

    server.on('upgrade', function (req, socket, head) {
      options.ui.writeLine('Proxying websocket to ' + req.url);
      proxy.ws(req, socket, head);
    });

    app.use(morgan('dev'));
    app.use(function(req, res) {
      return proxy.web(req, res);
    });
  }
};

module.exports = ProxyServerAddon;

'use strict';

function ProxyServerAddon(project) {
  this.project = project;
  this.name = 'proxy-server-middleware';
}

ProxyServerAddon.prototype.serverMiddleware = function(options) {
  var app = options.app, server = options.options.httpServer;
  options = options.options;

  if (options.proxy) {
    var proxy = require('http-proxy').createProxyServer({
      target: options.proxy,
      ws: true,
      secure: !options.insecureProxy,
      changeOrigin: true,
      xfwd: true
    });

    proxy.on('error', function (e) {
      options.ui.writeLine('Error proxying to ' + options.proxy);
      options.ui.writeError(e);
    });

    var morgan = require('morgan');

    options.ui.writeLine('Proxying to ' + options.proxy);

    server.on('upgrade', function (req, socket, head) {
      options.ui.writeLine('Proxying websocket to ' + req.url);
      proxy.ws(req, socket, head);
    });

    app.use(morgan('dev'));
    app.use(function(req, res) {
      return proxy.web(req, res);
    });
  }
};

module.exports = ProxyServerAddon;

Enable X-Forwarded-* headers in http-proxy


import { run } from '@ember/runloop';
import Helper from '@ember/component/helper';
import { get, observer, computed } from '@ember/object';
import { inject as service } from '@ember/service';

export default Helper.extend({
  moment: service(),
  disableInterval: false,
  globalAllowEmpty: computed.bool('moment.__config__.allowEmpty'),
  supportsGlobalAllowEmpty: true,
  localeOrTimeZoneChanged: observer('moment.locale', 'moment.timeZone', function() {
    this.recompute();
  }),

  compute(value, { interval }) {
    if (get(this, 'disableInterval')) { return; }

    this.clearTimer();

    if (interval) {
      /*
       * NOTE: intentionally a setTimeout so tests do not block on it
       * as the run loop queue is never clear so tests will stay locked waiting
       * for queue to clear.
       */
      this.intervalTimer = setTimeout(() => {
        run(() => this.recompute());
      }, parseInt(interval, 10));
    }
  },

  morphMoment(time, { locale, timeZone }) {
    const momentService = get(this, 'moment');

    locale = locale || get(momentService, 'locale');
    timeZone = timeZone || get(momentService, 'timeZone');

    if (locale && time.locale) {
      time = time.locale(locale);
    }

    if (timeZone && time.tz) {
      time = time.tz(timeZone);
    }

    return time;
  },

  clearTimer() {
    clearTimeout(this.intervalTimer);
  },

  destroy() {
    this.clearTimer();
    this._super(...arguments);
  }
});

import { run } from '@ember/runloop';
import Helper from '@ember/component/helper';
import { get, observer, computed } from '@ember/object';
import { inject as service } from '@ember/service';

export default Helper.extend({
  moment: service(),
  disableInterval: false,
  globalAllowEmpty: computed('moment.__config__.allowEmpty', function() {
    return this.get('moment.__config__.allowEmpty');
  }),
  supportsGlobalAllowEmpty: true,
  localeOrTimeZoneChanged: observer('moment.locale', 'moment.timeZone', function() {
    this.recompute();
  }),

  compute(value, { interval }) {
    if (get(this, 'disableInterval')) { return; }

    this.clearTimer();

    if (interval) {
      /*
       * NOTE: intentionally a setTimeout so tests do not block on it
       * as the run loop queue is never clear so tests will stay locked waiting
       * for queue to clear.
       */
      this.intervalTimer = setTimeout(() => {
        run(() => this.recompute());
      }, parseInt(interval, 10));
    }
  },

  morphMoment(time, { locale, timeZone }) {
    const momentService = get(this, 'moment');

    locale = locale || get(momentService, 'locale');
    timeZone = timeZone || get(momentService, 'timeZone');

    if (locale && time.locale) {
      time = time.locale(locale);
    }

    if (timeZone && time.tz) {
      time = time.tz(timeZone);
    }

    return time;
  },

  clearTimer() {
    clearTimeout(this.intervalTimer);
  },

  destroy() {
    this.clearTimer();
    this._super(...arguments);
  }
});

Work around a problem in later (currently unsupported) embers where Ember.computed.bool is not a function


module.exports = {
  assets: {
    files: [
      {expand: true, src: ["images/**"], dest: "dist/"}
    ]
  }
};

module.exports = {
  assets: {
    files: [
      {expand: true, src: ["assets/**"], dest: "dist/"}
    ]
  }
};

Fix wrong asset path being copied into dist folder.


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

module.exports = {
  devtool: 'eval',
  entry: [
    'webpack-dev-server/client?http://localhost:3000',
    'webpack/hot/only-dev-server',
    './src/index'
  ],
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js',
    publicPath: '/static/'
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin()
  ],
  module: {
    loaders: [{
      test: /\.js$/,
      loaders: ['react-hot', 'babel'],
      include: path.join(__dirname, 'src')
    }]
  }
};

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

module.exports = {
  devtool: 'eval',
  entry: [
    'webpack-dev-server/client?https://notica.us',
    'webpack/hot/only-dev-server',
    './src/index'
  ],
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js',
    publicPath: '/static/'
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin()
  ],
  watchOptions: {
    poll: true
  },
  module: {
    loaders: [{
      test: /\.js$/,
      loaders: ['react-hot', 'babel'],
      include: path.join(__dirname, 'src')
    }]
  }
};

Make HMR work when app is ran on web host


'use strict';

const Merger = require('../lib/merger')
  , path = require('path');
require('./_config');

describe('Solidity Merger', () => {

  it('should set default options', function () {
    let merger = new Merger();
    assert.equal(merger.delimeter, '\n\n', 'Delimeter must be set to 2 new lines');
    assert.isArray(merger.processedFiles, 'Must be initialized as array');
  });

  it('should import relative files', async () => {
    let merger = new Merger({ delimeter: '\n\n' });
    let file = path.join(__dirname, '/contracts/LocalImports.sol');

    let result = await merger.processFile(file, true);
    assertWithFile(result, 'LocalImports.sol');
  });

  it('should not import twice same ', async () => {
    let merger = new Merger({ delimeter: '\n\n' });
    let file = path.join(__dirname, '/contracts/MultiImports.sol');

    let result = await merger.processFile(file, true);

    assertWithFile(result, 'MultiImports.sol');
  });

});

'use strict';

const Merger = require('../lib/merger')
  , path = require('path')
  , { merge } = require('../index');
require('./_config');

describe('Solidity Merger', () => {

  it('should set default options', function () {
    let merger = new Merger();
    assert.equal(merger.delimeter, '\n\n', 'Delimeter must be set to 2 new lines');
    assert.isArray(merger.processedFiles, 'Must be initialized as array');
  });

  it('should import relative files', async () => {
    let merger = new Merger({ delimeter: '\n\n' });
    let file = path.join(__dirname, '/contracts/LocalImports.sol');

    let result = await merger.processFile(file, true);
    assertWithFile(result, 'LocalImports.sol');
  });

  it('should import relative files using merge', async () => {
    let file = path.join(__dirname, '/contracts/LocalImports.sol');
    let result = merge(file);
    assertWithFile(result, 'LocalImports.sol');
  });

  it('should not import twice same ', async () => {
    let merger = new Merger({ delimeter: '\n\n' });
    let file = path.join(__dirname, '/contracts/MultiImports.sol');

    let result = await merger.processFile(file, true);

    assertWithFile(result, 'MultiImports.sol');
  });

});

Add test for merge function


// User-specific configuration
exports.sentiment_keyword = "education";       // keyword to monitor in Twitter
exports.sentiment_analysis_frequency_sec = 30; // analyze sentiment every N seconds

// Create the credentials object for export
exports.credentials = {};

// Watson Tone Analyzer
// https://www.ibm.com/watson/developercloud/tone-analyzer.html
exports.credentials.tone_analyzer = {
    password: '',
    username: ''
};

// Twitter
exports.credentials.twitter = {
    consumer_key: '',
    consumer_secret: '',
    access_token_key: '',
    access_token_secret: ''
};

/*
User-specific configuration
    ** IMPORTANT NOTE ********************
    * Please ensure you do not interchange your username and password.
    * Hint: Your username is the lengthy value ~ 36 digits including a hyphen
    * Hint: Your password is the smaller value ~ 12 characters
*/

exports.sentiment_keyword = "education";       // keyword to monitor in Twitter
exports.sentiment_analysis_frequency_sec = 30; // analyze sentiment every N seconds

// Create the credentials object for export
exports.credentials = {};

// Watson Tone Analyzer
// https://www.ibm.com/watson/developercloud/tone-analyzer.html
exports.credentials.tone_analyzer = {
    password: '',
    username: ''
};

// Twitter
exports.credentials.twitter = {
    consumer_key: '',
    consumer_secret: '',
    access_token_key: '',
    access_token_secret: ''
};

Add note regarding username/password interchange.


window.onload = () => {
    var instance = new Index();

    var filePath = document.getElementById('filePath');
    var createIndexButton = document.getElementById('createIndexButton');
    var terms = document.getElementById('terms');
    var searchButton = document.getElementById('searchButton');
    var display = document.getElementById('display');

    createIndexButton.addEventListener('click', function(e) {
        instance.createIndex(filePath.files[0]);
    });

    searchButton.addEventListener('click', function(e) {
        instance.searchIndex(terms.value);
    });
}

window.onload = () => {
    var instance = new Index();

    var filePath = document.getElementById('filePath');
    var createIndexButton = document.getElementById('createIndexButton');
    var terms = document.getElementById('terms');
    var searchButton = document.getElementById('searchButton');
    var display = document.getElementById('display');

    createIndexButton.addEventListener('click', function(e) {
        var indexArray = instance.createIndex(filePath.files[0]);
    });

    searchButton.addEventListener('click', function(e) {
        instance.searchIndex(terms.value);
    });
}

Add an instance of createIndex


'use strict';

var React = require('react'),
    App = require('./App');

React.render(<App />, document.body);

'use strict';

var React = require('react'),
    App = require('./app');

React.render(<App />, document.body);

Fix bug filename : App -> app


import React from 'react';
import moment from 'moment';
import {translate} from 'react-i18next';

const formatTime = (time: Date, t: Function) => {
  const now = moment();
  let lookup = 'TIME.';
  let options = {};

  if(now.diff(time, 'days') === 0) {
    lookup += 'TODAY';
  } else if (now.diff(time, 'days') === 1) {
    lookup += 'YESTERDAY';
  } else if (now.diff(time, 'weeks') === 0) {
    lookup += 'DAYS_AGO';
    options.days = now.diff(time, 'days');
  } else if (now.diff(time, 'months') === 0) {
    lookup += 'WEEKS_AGO';
    options.weeks = now.diff(time, 'weeks');
  } else if (now.diff(time, 'years' > 1)) {
    lookup += 'NOT_AVAILABLE';
  } else {
    lookup += 'MONTHS_AGO';
    options.months = now.diff(time, 'months');
  }

  return t(lookup, options);
};

const Time = translate()(({time, t}) =>
  <time dateTime={time.toISOString()}>
    {
      formatTime(time, t)
    }
  </time>
);

export default Time;

import React from 'react';
import moment from 'moment';
import {translate} from 'react-i18next';

const formatTime = (time: Date, t: Function) => {
  const now = moment();
  let lookup = 'TIME.';
  let options = {};

  if(now.diff(time, 'days') === 0) {
    lookup += 'TODAY';
  } else if (now.diff(time, 'days') === 1) {
    lookup += 'YESTERDAY';
  } else if (now.diff(time, 'weeks') === 0) {
    lookup += 'DAYS_AGO';
    options.days = now.diff(time, 'days');
  } else if (now.diff(time, 'months') === 0) {
    lookup += 'WEEKS_AGO';
    options.weeks = now.diff(time, 'weeks');
  } else if (now.diff(time, 'years' > 1)) {
    lookup += 'NOT_AVAILABLE';
  } else {
    lookup += 'MONTHS_AGO';
    options.months = now.diff(time, 'months');
  }

  return t(lookup, options);
};

const Time = translate()(({time, t}) =>
  <time dateTime={time.toISOString()}>
    {
      formatTime(time, t)
    }
    {moment().diff(time, 'days') < 2 && ' '+time.getHours()+':'+time.getMinutes()}
  </time>
);

export default Time;

Add more accurate time to unit observations


'use strict';

var React = require('react');

// Styles
var compStyles = require('./ChartView.module.css');

var ChartView = React.createClass({
	shouldComponentUpdate: function () {
		return false;
	},
	componentDidMount: function () {
		var {appState, callback} = this.props,
			{root} = this.refs;
		require.ensure(['./chart'], function () {
			var chart = require('./chart');
			chart(root, callback, {xena: JSON.stringify(appState)});
		});
	},
	render: function () {
		return <div ref='root' className={compStyles.ChartView}/>;
	}
});

module.exports = ChartView;

'use strict';

var React = require('react');
var _ = require('./underscore_ext');

// Styles
var compStyles = require('./ChartView.module.css');

var ChartView = React.createClass({
	shouldComponentUpdate: function () {
		return false;
	},
	componentDidMount: function () {
		this.chartRender(this.props);
	},
	componentWillReceiveProps(newProps) {
		// Updating this way is clumsy. Need to refactor chart view.
		if (!_.isEqual(_.omit(this.props.appState, 'chartState'),
				_.omit(newProps.appState, 'chartState'))) {
			this.chartRender(newProps);
		}
	},
	chartRender(props) {
		var {appState, callback} = props,
			{root} = this.refs;
		require.ensure(['./chart'], function () {
			var chart = require('./chart');
			root.innerHTML = '';
			chart(root, callback, {xena: JSON.stringify(appState)});
		});
	},
	render: function () {
		return <div ref='root' className={compStyles.ChartView}/>;
	}
});

module.exports = ChartView;

Update chart view on state changes.


import Ember from 'ember';
import layout from '../templates/components/flexberry-map';
import ContainerMixin from 'ember-flexberry-gis/mixins/layercontainer';

export default Ember.Component.extend(ContainerMixin, {
  layout,

  model: undefined,

  center: Ember.computed('model.lat', 'model.lng', function () {
    return L.latLng(this.get('model.lat'), this.get('model.lng'));
  }),

  zoom: Ember.computed('model.zoom', function() {
    return this.get('model.zoom');
  }),

  leafletMap: undefined,

  didInsertElement() {
    this._super(...arguments);
    let map = L.map(this.element, this.get('options'));
    map.setView(this.get('center'), this.get('zoom'));
    this.set('leafletMap', map);
    this.buildLayers(map);
    this.setOrder({ index: 0 });
  },

  willDestoryElement() {
    var leafletMap = this.get('leafletMap');
    if (leafletMap) {
      leafletMap.remove();
      this.set('leafletMap', null);
    }
  }
});

import Ember from 'ember';
import layout from '../templates/components/flexberry-map';
import ContainerMixin from 'ember-flexberry-gis/mixins/layercontainer';

export default Ember.Component.extend(ContainerMixin, {
  layout,

  model: undefined,

  center: Ember.computed('model.lat', 'model.lng', function () {
    return L.latLng(this.get('model.lat') || 0, this.get('model.lng') || 0);
  }),

  zoom: Ember.computed('model.zoom', function() {
    return this.get('model.zoom');
  }),

  leafletMap: undefined,

  didInsertElement() {
    this._super(...arguments);
    let map = L.map(this.element, this.get('options'));
    map.setView(this.get('center'), this.get('zoom'));
    this.set('leafletMap', map);
    this.buildLayers(map);
    this.setOrder({ index: 0 });
  },

  willDestoryElement() {
    var leafletMap = this.get('leafletMap');
    if (leafletMap) {
      leafletMap.remove();
      this.set('leafletMap', null);
    }
  }
});

Add default value for map center


(function($,undefined){

    $(document).on('click', '.delete-confirm', function(){
        var $this = $(this);
        $('#DeleteUser').find('#confirmDeleteUser').data('url', $this.attr('href'));
        $('#DeleteUser').modal('show');
        return false;
    });

    $(document).on('click', '#confirmDeleteUser', function(){
        var $this = $(this);
        $this.button('loading');
        window.location.href = $this.data('url');
    });

    $(function(){
        $('input').addClass('form-control');
    });

})($);

(function($,undefined){

    $(document).on('click', '.delete-confirm', function(){
        var $this = $(this);
        $('#DeleteUser').find('#confirmDeleteUser').data('url', $this.attr('href'));
        $('#DeleteUser').modal('show');
        return false;
    });

    $(document).on('click', '#confirmDeleteUser', function(){
        var $this = $(this);
        $this.button('loading');
        window.location.href = $this.data('url');
    });

    $(function(){
        $('input').addClass('form-control');
        $('select').addClass('form-control');
        $('textarea').addClass('form-control');
    });

})($);

Add select and tex area glodal class


'use strict';

const hooks = require('./hooks');
const Promise = require('bluebird');

module.exports = function(){
  const app = this;

  app.use('/entryproducts', {
    find() {
      const sequelize = app.get('sequelize');
      var products = [], idsResult = [];
      return sequelize.models['Entry'].findAll({
        attributes: [
          [sequelize.fn('COUNT', sequelize.col('ProductId')), 'count'],
          'ProductId'
        ],
        group: ['ProductId'],
        where: {
          ProductId: {
            $ne: null
          }
        }
      }).then(ids => {
        idsResult = ids.map(id => id.dataValues);
        return sequelize.models['Product'].findAll({
          attributes: ['id', 'barcode', 'vendor', 'name', 'detailname'],
          where: {
            id: {
              $in: ids.map(itm => {
                return itm.ProductId
              })
            }
          }
        })
      }).then(products => {
        return products.map(product => {
            product = product.dataValues;
            let id = idsResult.filter(itm => {
              return itm.ProductId === product.id;
            })[0];
            product = Object.assign(product,id);
            delete product.ProductId;
            return product;
        })
      })
    }
  });

  // Get our initialize service to that we can bind hooks
  const entryProductsService = app.service('/entryproducts');
  // Set up our before hooks
  entryProductsService.before(hooks.before);
  // Set up our after hooks
  entryProductsService.after(hooks.after);

};

'use strict';

const hooks = require('./hooks');
const Promise = require('bluebird');

module.exports = function(){
  const app = this;

  app.use('/entryproducts', {
    find() {
      const sequelize = app.get('sequelize');
      var products = [], idsResult = [];
      return sequelize.models['Entry'].findAll({
        attributes: [
          [sequelize.fn('COUNT', sequelize.col('ProductId')), 'count'],
          'ProductId'
        ],
        group: ['ProductId'],
        where: {
          ProductId: {
            $ne: null
          }
        }
      }).then(ids => {
        idsResult = ids.map(id => id.dataValues);
        return sequelize.models['Product'].findAll({
          attributes: ['id', 'barcode', 'vendor', 'name', 'detailname', 'createdAt'],
          limit: 20,
          order: [['updatedAt', 'DESC']],
          where: {
            id: {
              $in: ids.map(itm => {
                return itm.ProductId
              })
            }
          }
        })
      }).then(products => {
        return products.map(product => {
            product = product.dataValues;
            let id = idsResult.filter(itm => {
              return itm.ProductId === product.id;
            })[0];
            product = Object.assign(product,id);
            delete product.ProductId;
            return product;
        })
      })
    }
  });

  // Get our initialize service to that we can bind hooks
  const entryProductsService = app.service('/entryproducts');
  // Set up our before hooks
  entryProductsService.before(hooks.before);
  // Set up our after hooks
  entryProductsService.after(hooks.after);

};

Sort entryproducts api by latest entrys, limit to 20


var ColorThief = require('color-thief')
, rgbToHex = require('rgb-hex')

var colorThief = new ColorThief()

module.exports = {
  getPalette: getPalette,
  rgbArrayToHex: rgbArrayToHex
}

function getPalette(imgPath) {
  return colorThief.getPalette(imgPath)
}

function rgbArrayToHex(rgbArray) {
  return rgbToHex.apply(this, rgbArray)
}

function process(imgPath) {
  return getPalette(imgPath).slice(0,6).map(rgbArrayToHex)
}

var ColorThief = require('color-thief')
, rgbToHex = require('rgb-hex')

var colorThief = new ColorThief()

module.exports = {
  getPalette: getPalette,
  rgbArrayToHex: rgbArrayToHex,
  process: process
}

function getPalette(imgPath) {
  return colorThief.getPalette(imgPath)
}

function rgbArrayToHex(rgbArray) {
  return rgbToHex.apply(this, rgbArray)
}

function process(imgPath) {
  return getPalette(imgPath).slice(0,5).map(rgbArrayToHex)
}

Change default number of colors reported (6 --> 5)


/* eslint-disable no-use-before-define */
if (typeof setImmediate !== 'function') {
  var setImmediate = fn => setTimeout(fn, 0);
}

const next = (iter, callbacks, prev = undefined) => {
  const { onNext, onComplete } = callbacks;
  const item = iter.next(prev);
  const value = item.value;

  if (item.done) {
    return onComplete();
  }

  onNext(value);
  setImmediate(() => next(iter, callbacks, value));
};

const ogen = (fn) => (...args) => ({
  subscribe: (onNext, onError, onComplete) => {
    next(fn(...args), { onNext, onError, onComplete });
  }
});

module.exports = ogen.ogen = ogen.default = ogen;

Fix setImmediate is not a function


var _data_list = [];

function fetchDataAndRenderContent () {
  console.log("fetchDataAndRenderContent first time!");
  _data_list = [];
  renderCharts();
  extractDataAndUpdateContent();
}

function extractDataAndUpdateContent () {
  updateFetchProgress(100);

  renderGaugeRowItemsWithAnimation(extractGauageRowData());
  updateCharts();

  updateFetchCounter();
  updateFetchProgress(0);
}

function extractGauageRowData () {
  if (!_data_list.length) {
    fetchMockupData();
  }
  var _list = _data_list.slice(-1)[0];
  var _data = $.extend(true, {}, gauge_data);
  $.each(_data, function (index, item) {
    item.time = _list[index].time;
    item.value = _list[index].value;
  });
  return _data;
}

function fetchMockupData () {
  var _list = [];
  $.each(gauge_data, function (index, item) {
    var _item = {};
    _item.time = new Date();
    _item.value = item.value * (1 + (Math.random() - 0.5) * 0.1);
    _list.push(_item);
  });
  _data_list.push(_list);
}

var _data_list = [];

function fetchDataAndRenderContent () {
  console.log("fetchDataAndRenderContent first time!");
  _data_list = [];
  renderCharts();
  extractDataAndUpdateContent();
}

function extractDataAndUpdateContent () {
  updateFetchProgress(100);

  renderGaugeRowItemsWithAnimation(extractGauageRowData());
  updateCharts();

  updateFetchCounter();
  updateFetchProgress(0);
}

function extractGauageRowData () {
  if (!_data_list.length) {
    fetchMockupData();
  }
  var _set = _data_list.slice(-1)[0];
  var _data = $.extend(true, {}, gauge_data);
  $.each(_data, function (index, item) {
    item.time = _set[item.id].time;
    item.value = _set[item.id].value;
  });
  return _data;
}

function fetchMockupData () {
  var _set = [];
  $.each(gauge_data, function (index, item) {
    var _item = {};
    _item.time = new Date();
    _item.value = item.value * (1 + (Math.random() - 0.5) * 0.1);
    _set[item.id] = _item;
  });
  _data_list.push(_set);
}

Update _data_list structure for charts


import * as katex from './katex-import.js';

export class KatexInline extends HTMLElement {

  constructor() {
    super();
    this.attachShadow({mode: 'open'});
    this.shadowRoot.innerHTML = `

      <link rel="stylesheet" href="./node_modules/katex/dist/katex.min.css">
      <link rel="stylesheet" href="../katex/dist/katex.min.css">

    `;
    this._container = this.shadowRoot.querySelector('div');
  }

  get _displayMode() { return false; }

  connectedCallback() {
    katex.render(this.textContent, this._container, { displayMode: this._displayMode });
  }
}
customElements.define('katex-inline', KatexInline);

Update comment wording from "should" to "might"


// @flow
import { PureComponent } from 'react'
import scrollParent from 'scrollparent'
import SweetScroll from 'sweet-scroll'

import type { Children } from 'react'

import Wrapper from './Wrapper'

type Props = {
  width: number,
  currentPageOrder: number,
  children?: ?Children,
}

export default class Scroller extends PureComponent<void, Props, void> {
  static scrollOptions = {
    duration: 500,
    // easing: 'easeOutExpo',
    easing: 'easeOutQuint',
    verticalScroll: true,
    horizontalScroll: false,
    // quickMode: true,
  }

  // for lint
  props: Props
  scroller: SweetScroll

  componentDidUpdate ({ currentPageOrder: prevCurrentPageOrder }: Props) {
    const { currentPageOrder, width } = this.props
    if (currentPageOrder !== prevCurrentPageOrder) {
      // NOTE: 16px: spacing between pages
      // FIXME: adjust size params automatically
      this.scroller.toTop(currentPageOrder * (768 * (width / 1024) + 16))
    }
  }

  render () {
    return (
      <Wrapper
        innerRef={(el) => {
          this.scroller = new SweetScroll(Scroller.scrollOptions, scrollParent(el))
        }}
      >
        { this.props.children }
      </Wrapper>
    )
  }
}

// @flow
import { PureComponent } from 'react'
import scrollParent from 'scrollparent'
import SweetScroll from 'sweet-scroll'

import type { Children } from 'react'

import Wrapper from './Wrapper'

type Props = {
  width: number,
  currentPageOrder: number,
  children?: ?Children,
}

export default class Scroller extends PureComponent<void, Props, void> {
  static scrollOptions = {
    duration: 500,
    // easing: 'easeOutExpo',
    easing: 'easeOutQuint',
    verticalScroll: true,
    horizontalScroll: false,
    // quickMode: true,
  }

  // for lint
  props: Props
  el: HTMLElement

  componentDidUpdate ({ currentPageOrder: prevCurrentPageOrder }: Props) {
    const { currentPageOrder, width } = this.props
    if (currentPageOrder !== prevCurrentPageOrder) {
      // NOTE: 16px: spacing between pages
      // FIXME: adjust size params automatically
      const scroller = new SweetScroll(Scroller.scrollOptions, scrollParent(this.el))
      scroller.toTop(currentPageOrder * (768 * (width / 1024) + 16))
    }
  }

  render () {
    return (
      <Wrapper innerRef={(el) => { this.el = el }}>
        { this.props.children }
      </Wrapper>
    )
  }
}

Create SweetScroll instance after updated current page order


'use strict';

var fs = require('fs');
var Promise = require('es6-promise').Promise;
var sqlite3 = require('sqlite3');

var file = 'sitemap.db';
var dbExists = fs.existsSync(file);
var db = new sqlite3.Database(file);

module.exports = {
    initialize: function () {
        db.serialize(function() {
            if (!dbExists) {
                db.exec('CREATE TABLE Urls (url TEXT UNIQUE, lastmod TEXT)');
            }
        });
    },

    get: function (url) {
        return new Promise(function (resolve, reject) {
            db.get('SELECT * FROM Urls WHERE url="' + url + '";', function (err, row) {
                resolve(row);
            });
        });
    },

    update: function (url, lastMod) {
        return new Promise(function (resolve, reject) {
            // add or update
            var sqlStatement = 'INSERT OR IGNORE INTO Urls (url, lastmod) VALUES("' + url + '", "' + lastMod + '");' +
                'UPDATE Urls SET lastmod = "' + lastMod + '" WHERE url="' + url+ '";';
            db.exec(sqlStatement, resolve);
        });
    },
};

'use strict';

var fs = require('fs');
var Promise = require('es6-promise').Promise;
var sqlite3 = require('sqlite3');

var file = __dirname + '/../sitemap.db';
var dbExists = fs.existsSync(file);
var db = new sqlite3.Database(file);

module.exports = {
    initialize: function () {
        db.serialize(function() {
            if (!dbExists) {
                db.exec('CREATE TABLE Urls (url TEXT UNIQUE, lastmod TEXT)');
            }
        });
    },

    get: function (url) {
        return new Promise(function (resolve, reject) {
            db.get('SELECT * FROM Urls WHERE url="' + url + '";', function (err, row) {
                resolve(row);
            });
        });
    },

    update: function (url, lastMod) {
        return new Promise(function (resolve, reject) {
            // add or update
            var sqlStatement = 'INSERT OR IGNORE INTO Urls (url, lastmod) VALUES("' + url + '", "' + lastMod + '");' +
                'UPDATE Urls SET lastmod = "' + lastMod + '" WHERE url="' + url+ '";';
            db.exec(sqlStatement, resolve);
        });
    },
};

Change sitemap.db path to module root


var mode = 0; //primary

function calc_mode() {
	var modes = ["primary", "secondary", "tertiary"];
	return modes[mode];
}

$(function() {
	$(".add").button();
	$(".edit").button();
	$(".delete").button().click(function() {
		var res = confirm("Are you sure you want to delete this item?");
		if (res)
			window.location.href=$(this).attr('href');
		else
			return false;
	});
	$(".view").button();
	$(".submit").button();

	$("#ingredients_table table").tablesorter();
	$("#effects_table table").tablesorter();
});

var mode = 0; //primary

function calc_mode() {
	var modes = ["primary", "secondary", "tertiary"];
	return modes[mode];
}

$(function() {
	$(".add").button();
	$(".edit").button();
	$(".delete").button().click(function() {
		var res = confirm("Are you sure you want to delete this item?");
		if (res)
			window.location.href=$(this).attr('href');
		else
			return false;
	});
	$(".view").button();
	$(".submit").button();

	$("#ingredients_table table").tablesorter();
	$("#effects_table table").tablesorter();

	$("#calc_ingredients tbody").find('tr').each(function(){
		$(this).click(function(){
			$('#'+calc_mode()).html($(this).text());
		});
	});
});

Add ingredients table row click handler


class Resource {
  constructor(region, id, tagMap) {
    this._region = region;
    this._id = id;
    this._tagMap = tagMap || new Map();
  }

  get region() { return this._region; }
  get id() { return this._id; }
  get tagMap() { return this._tagMap; }

  get title() { return null; }
  get link() { return null; }
}

class Ec2Instance extends Resource {
  get title() {
    const name = this.tagMap.get('Name');
    return `:ec2: Instance ${this.id}` + (name ? ` (${name})` : '');
  }
  get link() {
    return `https://console.aws.amazon.com/ec2/v2/home?region=${this.region}#Instances:instanceId=${this.id}`;
  }
}

class RdsDbCluster extends Resource {
  get title() {
    return `:rds: RDS ${this.id}`;
  }
}

class Vpc extends Resource {
  get title() {
    const name = this.tagMap.get('Name');
    return `:vpc: VPC ${this.id}` + (name ? ` (${name})` : '');
  }
}

export default Resource;
export {
  Ec2Instance,
  RdsDbCluster,
  Vpc,
};

class Resource {
  constructor(region, id, tagMap) {
    this._region = region;
    this._id = id;
    this._tagMap = tagMap || new Map();
  }

  get region() { return this._region; }
  get id() { return this._id; }
  get tagMap() { return this._tagMap; }

  get title() { return null; }
  get link() { return null; }
}

class Ec2Instance extends Resource {
  get title() {
    const name = this.tagMap.get('Name');
    return `:ec2: Instance ${this.id}` + (name ? ` (${name})` : '');
  }
  get link() {
    return `https://console.aws.amazon.com/ec2/v2/home?region=${this.region}#Instances:instanceId=${this.id}`;
  }
}

class RdsDbCluster extends Resource {
  get title() {
    return `:rds: RDS ${this.id}`;
  }
}

class Vpc extends Resource {
  get title() {
    const name = this.tagMap.get('Name');
    return `:vpc: VPC ${this.id}` + (name ? ` (${name})` : '');
  }

  get link() {
    return `https://console.aws.amazon.com/vpc/home?region=${this.region}#vpcs:filter=${this.id}`;
  }
}

export default Resource;
export {
  Ec2Instance,
  RdsDbCluster,
  Vpc,
};

Add link to vpc in console


"use strict";

module.exports = {
    // cache system (see https://github.com/BryanDonovan/node-cache-manager)
    Cache: {
        store: "memory",
        max: 5000,
        ttl: 1800
    },
    // default Park Settings
    DefaultParkName: "Default Park",
    DefaultParkTimezone: "Europe/London",
    DefaultParkTimeFormat: null,
    // cache settings (in seconds)
    DefaultCacheWaitTimesLength: 60 * 5, // 5 minutes
    DefaultCacheOpeningTimesLength: 60 * 60, // 1 hour
    // default time return format
    DefaultTimeFormat: "YYYY-MM-DDTHH:mm:ssZ",
    // default date return format
    DefaultDateFormat: "YYYY-MM-DD",
};

"use strict";

var cacheManager = require("cache-manager");

module.exports = {
    // cache system (see https://github.com/BryanDonovan/node-cache-manager)
    Cache: cacheManager.caching({
        store: "memory",
        max: 5000,
        ttl: 60 * 60
    }),
    // default Park Settings
    DefaultParkName: "Default Park",
    DefaultParkTimezone: "Europe/London",
    DefaultParkTimeFormat: null,
    // cache settings (in seconds)
    DefaultCacheWaitTimesLength: 60 * 5, // 5 minutes
    DefaultCacheOpeningTimesLength: 60 * 60, // 1 hour
    // default time return format
    DefaultTimeFormat: "YYYY-MM-DDTHH:mm:ssZ",
    // default date return format
    DefaultDateFormat: "YYYY-MM-DD",
};

FIX - not initialising cache when no cache is supplied


import ATV from 'atvjs';
// templates
import listTemplate from './templates/list.jade';

let myPageStyles = `
.text-bold {
    font-weight: bold;
}
.text-white {
    color: rgb(255, 255, 255);
}
`;

App.onLaunch = function (options) {
    var demoPage = ATV.Page.create({
        name: 'demo',
        style: myPageStyles,
        template: listTemplate,
        data: {
          title: 'Demo',
          results: [
            {
              id: 1,
              style: '',
              title: 'First item',
              preview: {
                url: ''
                style: ''
                title:'First Preview'
              }
            }
          ]
        }
    });
    // create menu page
    ATV.Menu.create({
        // any attributes that you want to set on the root level menuBar element of TVML
        attributes: {},
        // array of menu item configurations
        items: [{
            id: 'top',
            name: 'Top'
        }, {
            id: 'demo',
            name: 'Demo',
            page: demoPage
        }]
    });
    ATV.Navigation.navigateToMenuPage();
};

App.onWillResignActive = function() {

}

App.onDidEnterBackground = function() {

}

App.onWillEnterForeground = function() {

}

App.onDidBecomeActive = function() {

}

App.onWillTerminate = function() {

}

import ATV from 'atvjs';
// templates
import listTemplate from './templates/list.jade';

let myPageStyles = `
.text-bold {
    font-weight: bold;
}
.text-white {
    color: rgb(255, 255, 255);
}
`;

App.onLaunch = function (options) {
    var demoPage = ATV.Page.create({
        name: 'demo',
        style: myPageStyles,
        template: listTemplate,
        data: {
          title: 'Demo',
          results: [
            {
              id: 1,
              style: '',
              title: 'First item',
              preview: {
                url: '',
                style: '',
                title:'First Preview'
              }
            }
          ]
        }
    });
    // create menu page
    ATV.Menu.create({
        // any attributes that you want to set on the root level menuBar element of TVML
        attributes: {},
        // array of menu item configurations
        items: [{
            id: 'top',
            name: 'Top'
        }, {
            id: 'demo',
            name: 'Demo',
            page: demoPage
        }]
    });
    ATV.Navigation.navigateToMenuPage();
};

App.onWillResignActive = function() {

}

App.onDidEnterBackground = function() {

}

App.onWillEnterForeground = function() {

}

App.onDidBecomeActive = function() {

}

App.onWillTerminate = function() {

}

Fix code error in template


(function() {
  'use strict';

  // Load Google Analytics libraries
  GOVUK.Analytics.load();

  var cookieDomain = (document.domain === 'www.gov.uk') ? '.www.gov.uk' : document.domain;

  // Configure profiles and make interface public
  // for custom dimensions, virtual pageviews and events
  GOVUK.analytics = new GOVUK.Analytics({
    universalId: 'UA-97208357-1',
    cookieDomain: cookieDomain
  });

  ga('create', 'UA-145652997-1', 'auto', 'govuk_shared', {'allowLinker': true});
  ga('govuk_shared.require', 'linker');
  ga('govuk_shared.linker.set', 'anonymizeIp', true);
  ga('govuk_shared.linker:autoLink', [cookieDomain]);

  // Activate any event plugins eg. print intent, error tracking
  GOVUK.analyticsPlugins.error();
  GOVUK.analyticsPlugins.printIntent();

  // Track initial pageview
  GOVUK.analytics.trackPageview();

  // clicks on data-analytics-event
  $(document).on('click', '[data-analytics-event]', function(e){
    var $target = $(e.target);
    GOVUK.analytics.trackEvent('click', $target.data('analytics-event'), {
      label: e.target.innerText
    });
  });
})();

(function() {
  'use strict';

  // Load Google Analytics libraries
  GOVUK.Analytics.load();

  var cookieDomain = (document.domain === 'www.gov.uk') ? '.www.gov.uk' : document.domain;

  // Configure profiles and make interface public
  // for custom dimensions, virtual pageviews and events
  GOVUK.analytics = new GOVUK.Analytics({
    universalId: 'UA-97208357-1',
    cookieDomain: cookieDomain
  });

  ga('create', 'UA-145652997-1', 'auto', 'govuk_shared', {'allowLinker': true});
  ga('govuk_shared.require', 'linker');
  ga('govuk_shared.linker.set', 'anonymizeIp', true);
  ga('govuk_shared.linker:autoLink', [cookieDomain]);

  // Activate any event plugins eg. print intent, error tracking
  GOVUK.analyticsPlugins.error();
  GOVUK.analyticsPlugins.printIntent();

  // Track initial pageview
  GOVUK.analytics.trackPageview();

  // Cross domain event tracking
  GOVUK.analytics.addLinkedTrackerDomain('UA-145652997-1', 'govuk_shared', cookieDomain);

  // Clicks on data-analytics-event
  $(document).on('click', '[data-analytics-event]', function(e){
    var $target = $(e.target);
    GOVUK.analytics.trackEvent('click', $target.data('analytics-event'), {
      label: e.target.innerText
    });
  });
})();

Add cross domain event tracking


var ProjectBasedCollection = require('collections/project_based_collection');

var UserTalkCollections = ProjectBasedCollection.extend({
  url: function() {
    return "/talk/users/" + User.current.id + "?type=my_collections";
  },

  parse: function(response) {
    return _.map(response.my_collections, function(col) {
      return {
        id: col.zooniverse_id,
        image: col.subjects[0].location.standard,
        title: col.title,
        subjects: _.pluck(col.subjects, 'zooniverse_id'),
        thumbnail: col.subjects[0].location.thumbnail,
        description: col.description
      };
    });
  }
});

module.exports = UserTalkCollections;

var ProjectBasedCollection = require('collections/project_based_collection'),
  User = zooniverse.models.User;

var UserTalkCollections = ProjectBasedCollection.extend({
  url: function() {
    return "/talk/users/" + User.current.id + "?type=my_collections";
  },

  parse: function(response) {
    return _.map(response.my_collections, function(col) {
      return {
        id: col.zooniverse_id,
        image: col.subjects[0].location.standard,
        title: col.title,
        subjects: _.pluck(col.subjects, 'zooniverse_id'),
        thumbnail: col.subjects[0].location.thumbnail,
        description: col.description
      };
    });
  }
});

module.exports = UserTalkCollections;

Fix user bug in talk collections


/*jslint forin: true */

var log = console.log;

exports.report = function(file, lint) {
    log(file);

    var options = [], key, value,
        i, len, pad, e;

    for (key in lint.options) {
        value = lint.options[key];
        options.push(key + ": " + value);
    }
    log("/*jslint " + options.join(", ") + "*/");

    if (!lint.ok) {
        len = lint.errors.length;
        for (i=0; i<len; i++) {
            pad = '' + (i + 1);
            while (pad.length < 3) {
                pad = ' ' + pad;
            }
            e = lint.errors[i];
            if (e) {
                log(pad + ' ' + e.line + ',' + e.character + ': ' + e.reason);
                log( '    ' + (e.evidence || '').replace(/^\s+|\s+$/, ""));
            }
        }
    } else {
        log("ok!");
    }

    return lint.ok;
};

/*jslint forin: true */

var log = console.log;

exports.report = function(file, lint) {
    log(file);

    var options = [], key, value,
        i, len, pad, e;

    for (key in lint.options) {
        value = lint.options[key];
        options.push(key + ": " + value);
    }
    log("/*jslint " + options.join(", ") + " */");

    if (!lint.ok) {
        len = lint.errors.length;
        for (i=0; i<len; i++) {
            pad = '' + (i + 1);
            while (pad.length < 3) {
                pad = ' ' + pad;
            }
            e = lint.errors[i];
            if (e) {
                log(pad + ' ' + e.line + ',' + e.character + ': ' + e.reason);
                log( '    ' + (e.evidence || '').replace(/^\s+|\s+$/, ""));
            }
        }
    } else {
        log("ok!");
    }

    return lint.ok;
};

Add missing space to jslint config line.


import { GraphQLBoolean, GraphQLString } from 'graphql';
import { createClient } from 'redis';

import { redisUrl } from '../../config';

const startLive = {
  type: GraphQLBoolean,
  args: {
    id: { type: GraphQLString },
  },
  resolve(fieldName, { id }, context, { rootValue: request }) {
    return new Promise((resolve, reject) => {
      if (!request.user) {
        resolve(false);
      }

      const redis = createClient(redisUrl);
      redis.rpush('live', id, (err, reply) => {
        if (!err) {
          resolve(true);
        } else {
          reject(err);
        }
        redis.quit();
      });
    });
  }
};

export default startLive;

import { GraphQLBoolean, GraphQLString } from 'graphql';
import { createClient } from 'redis';

import { redisUrl } from '../../config';

const startLive = {
  type: GraphQLBoolean,
  args: {
    id: { type: GraphQLString },
  },
  async resolve(fieldName, { id }, context, { rootValue: request }) {
    const addLivePromise = new Promise((resolve, reject) => {
      if (!request.user) {
        resolve(false);
      }

      const redis = createClient(redisUrl);
      redis.rpush('live', id, (err, reply) => {
        redis.quit();
        if (!err) {
          resolve(true);
        } else {
          reject(err);
        }
      });
    });

    return await addLivePromise;
  }
};

export default startLive;

Fix add live promise problem


$().ready(() => {
  loadContentSection().then(() =>{
    $("#loader").addClass("hide");
    $("#real-body").removeClass("hide");
    $("#real-body").addClass("body");
  });
});

$("body").on('click', '.keyword', function() {
  $(this).addClass("active");
  $(".base").hide(200);
  $("#real-body").addClass("focus");
});

$("body").on('click', ".close", function(event) {
  event.stopPropagation();
  $(this).parent().removeClass("active");
  $(".base").show(200);
  $("#real-body").removeClass("focus");
});

$("body").on('click', ".active .item", function() {
  $(".item").off("click");
  const url = $(this).attr("data-url");
  window.location.href = url;
});

$(".level").on('click', function() {
  const isThisExtended = $(this).hasClass("extended");
  $(".extended").removeClass("extended");
  if (!isThisExtended) {
    $(this).addClass("extended");
  }
});

$().ready(() => {
  loadContentSection().then(() =>{
    $("#loader").addClass("hide");
    $("#real-body").removeClass("hide");
    $("#real-body").addClass("body");
  });
});

$("body").on('click', '.keyword', function() {
  $(this).addClass("active");
  $(".base").hide(200);
  $("#real-body").addClass("focus");
});

$("body").on('click', ".close", function(event) {
  event.stopPropagation();
  $(".extended").removeClass("extended");
  $(this).parent().removeClass("active");
  $(".base").show(200);
  $("#real-body").removeClass("focus");
});

$("body").on('click', ".active .item", function() {
  $(".item").off("click");
  const url = $(this).attr("data-url");
  window.location.href = url;
});

$("body").on('click', '.level-name', function() {
  const isThisExtended = $(this).parent().hasClass("extended");
  $(".extended").removeClass("extended");
  if (!isThisExtended) {
    $(this).parent().addClass("extended");
  }
});

Modify event listeners to use new html


if (process.env.NODE_ENV === 'development') {
  ['test1', 'test2'].forEach(createServiceWithName);
} else {
  throw Error('Test login handlers can only be registered on development servers for security reasons.');
}

function createServiceWithName(serviceName) {
  Accounts.registerLoginHandler(serviceName, function (options) {
      if (! options || ! options[serviceName]) {
        return undefined;
      }
      var selector = {};
      selector['services.' + serviceName + '.name'] = options[serviceName];
      var user = Meteor.users.findOne(selector);
      if (user) {
        return { userId: user._id };
      }
      var servicesObj = {};
      servicesObj[serviceName] = { name: options[serviceName] };
      var profileObj = {
        doNotOverride: options[serviceName] // Field shared among services
      };
      profileObj[serviceName + "-specific"] = options[serviceName];
      var newUserId = Accounts.insertUserDoc(options, {
        profile: profileObj,
        services: servicesObj
      });
      return {
          userId: newUserId
      };
  });
}

if (process.env.NODE_ENV === 'development') {
  ['test1', 'test2'].forEach(createServiceWithName);
} else {
  throw Error('Test login handlers can only be registered on development servers for security reasons.');
}

function createServiceWithName(serviceName) {
  Accounts.registerLoginHandler(serviceName, function (options) {
      if (! options || ! options[serviceName]) {
        return undefined;
      }
      var selector = {};
      selector['services.' + serviceName + '.name'] = options[serviceName];
      var user = Meteor.users.findOne(selector);
      if (user) {
        return { userId: user._id };
      }
      var servicesObj = {};
      servicesObj[serviceName] = { name: options[serviceName] };
      var profileObj = {
        doNotOverride: options[serviceName] // Field shared among services
      };
      profileObj[serviceName + "_specific"] = options[serviceName];
      var newUserId = Accounts.insertUserDoc(options, {
        profile: profileObj,
        services: servicesObj
      });
      return {
          userId: newUserId
      };
  });
}

Support profile.X_specific instead of profile['X-specific'].


import React from 'react';
import { ScrollView } from 'react-native';
import UserAccount from './UserAccount';
import CardPreferences from './CardPreferences';
import css from '../../styles/css';

// View for user to manage preferences, including which cards are visible
class PreferencesView extends React.Component {
	constructor(props) {
		super(props);
		this.state = {
			scrollEnabled: true
		};
	}

	toggleScroll = () => {
		this.setState({ scrollEnabled: !this.state.scrollEnabled });
	}

	render() {
		return (
			<ScrollView
				style={css.main_container}
				scrollEnabled={this.state.scrollEnabled}
			>
				<UserAccount />
				<CardPreferences
					toggleScroll={this.toggleScroll}
				/>
			</ScrollView>
		);
	}
}

export default PreferencesView;

import React from 'react';
import { ScrollView } from 'react-native';
import UserAccount from './UserAccount';
import CardPreferences from './CardPreferences';
import css from '../../styles/css';

// View for user to manage preferences, including which cards are visible
class PreferencesView extends React.Component {
	constructor(props) {
		super(props);
		this.state = {
			scrollEnabled: true
		};
	}

	toggleScroll = () => {
		this.setState({ scrollEnabled: !this.state.scrollEnabled });
	}

	render() {
		return (
			<ScrollView
				keyboardShouldPersistTaps={'handled'}
				style={css.main_container}
				scrollEnabled={this.state.scrollEnabled}
			>
				<UserAccount />
				<CardPreferences
					toggleScroll={this.toggleScroll}
				/>
			</ScrollView>
		);
	}
}

export default PreferencesView;

Fix double-click login button issue


import React from 'react'
import preload from '../public/data.json'
import ShowCard from './ShowCard'

const Search = React.createClass({
  render () {
    return (
      <div className='search'>
        {preload.shows.map((show) => {
          return (
            <ShowCard show={show} />
          )
        })}
      </div>
    )
  }
})

export default Search

import React from 'react'
import preload from '../public/data.json'
import ShowCard from './ShowCard'

const Search = React.createClass({
  render () {
    return (
      <div className='search'>
        {preload.shows.map((show) => {
          return (
            <ShowCard key={show.imdbID} show={show} />
          )
        })}
      </div>
    )
  }
})

export default Search

Add key prop to ShowCard.


var base = require('42-cent-base');
var util = require('util');
var Promise = require('bluebird');

function GatewayMock(options) {
  base.BaseGateway.call(this);
  this.options = options;
}

util.inherits(GatewayMock, base.BaseGateway);

GatewayMock.prototype.submitTransaction = function (order, cc, prospect, other) {

  var self = this;

  return GatewayMock.resolveValue ? Promise.resolve(GatewayMock.resolveValue).then(function (val) {
    GatewayMock.resolveValue = null;
    return val;
    }) : Promise.reject(GatewayMock.rejectValue || new Error('mock has no resolve value')).then(function (val) {
    GatewayMock.rejectValue = null;
    return val;
  });
};

GatewayMock.resolveWith = function resolveWith(val) {
  GatewayMock.resolveValue = val;
};

GatewayMock.rejectWith = function rejectValue(val) {
  GatewayMock.rejectValue = val;
};

module.exports = {
  factory: function (opt) {
    return new GatewayMock(opt);
  },
  GatewayMock: GatewayMock
};

var base = require('42-cent-base');
var util = require('util');
var P = require('bluebird');

function GatewayMock(options) {
  base.BaseGateway.call(this);
  this.options = options;
}

util.inherits(GatewayMock, base.BaseGateway);

GatewayMock.prototype.submitTransaction = function (order, cc, prospect, other) {

  var self = this;

  return GatewayMock.resolveValue ? P.resolve(GatewayMock.resolveValue).then(function (val) {
    GatewayMock.resolveValue = null;
    return val;
    }) : P.reject(GatewayMock.rejectValue || new Error('mock has no resolve value')).then(function (val) {
    GatewayMock.rejectValue = null;
    return val;
  });
};

GatewayMock.resolveWith = function resolveWith(val) {
  GatewayMock.resolveValue = val;
};

GatewayMock.rejectWith = function rejectValue(val) {
  GatewayMock.rejectValue = val;
};

module.exports = {
  factory: function (opt) {
    return new GatewayMock(opt);
  },
  GatewayMock: GatewayMock
};

Rename Promise var to avoid conflict with native promise


const fs = require('fs');
const path = require('path');

module.exports = function(options, fieldname, filename) {
  const dir = path.normalize(options.tempFileDir || process.cwd() + '/tmp/');

  if (!fs.existsSync(dir)) {
    fs.mkdirSync(dir);
  }
  let tempFilePath = path.join(dir, 'tmp' + Date.now());
  let writeStream = fs.createWriteStream(tempFilePath);
  let fileSize = 0; // eslint-disable-line

  return {
    handler: function(data) {
      writeStream.write(data);
      fileSize += data.length;
      if (options.debug) {
        return console.log( // eslint-disable-line
          `Uploaded ${data.length} bytes for `,
          fieldname,
          filename
        );
      }
    },
    getFilePath: function(){
      return tempFilePath;
    },
    getFileSize: function(){
      return fileSize;
    },
    cleanup: function(){
      writeStream.end();

      fs.unlink(tempFilePath, function(err) {
        if (err) throw err;
      });
    },
    complete: function(){
      writeStream.end();
    }
  };
};

const fs = require('fs');
const path = require('path');

module.exports = function(options, fieldname, filename) {
  const dir = path.normalize(options.tempFileDir || process.cwd() + '/tmp/');

  if (!fs.existsSync(dir)) {
    fs.mkdirSync(dir);
  }
  let tempFilePath = path.join(dir, 'tmp' + Date.now());
  let writeStream = fs.createWriteStream(tempFilePath);
  let fileSize = 0; // eslint-disable-line

  return {
    dataHandler: function(data) {
      writeStream.write(data);
      fileSize += data.length;
      if (options.debug) {
        return console.log( // eslint-disable-line
          `Uploaded ${data.length} bytes for `,
          fieldname,
          filename
        );
      }
    },
    getFilePath: function(){
      return tempFilePath;
    },
    getFileSize: function(){
      return fileSize;
    },
    cleanup: function(){
      writeStream.end();

      fs.unlink(tempFilePath, function(err) {
        if (err) throw err;
      });
    },
    complete: function(){
      writeStream.end();
    }
  };
};

Fix data handler name type


import React from 'react';
import { connect } from 'react-redux';

import Header from '../components/Header';

require('purecss');
require('../css/new.css');

const IndexView = React.createClass({
  render() {
    return (

        hello worldd

    );
  },
});

export default connect(
  (state) => (state)
)(IndexView);

import React from 'react';
import { connect } from 'react-redux';

import Header from '../components/Header';

require('purecss');

const IndexView = React.createClass({
  render() {
    return (

        hello worldd

    );
  },
});

export default connect(
  (state) => (state)
)(IndexView);

Remove link to old css file


import BikeshedBuilderConstants from '../constants/BikeshedBuilderConstants'

export function navigateAction (context) {
  context.dispatch(BikeshedBuilderConstants.RESET)
}

export function inputChange (context, payload) {
  context.dispatch(BikeshedBuilderConstants.INPUT_CHANGE, payload)
}

import BikeshedBuilderConstants from '../constants/BikeshedBuilderConstants'
import browserImageSize from 'browser-image-size'

export function navigateAction (context) {
  context.dispatch(BikeshedBuilderConstants.RESET)
}

export function inputChange (context, payload) {
  context.dispatch(BikeshedBuilderConstants.INPUT_CHANGE, payload)
}

export function submit () {
  console.warn('@TODO submit')
}

const { FileList, File } = global
export async function addImages (context, images: FileList) {
  images = await Promise.all(
    Array.from(images).map(getImageSize)
  )

  context.dispatch(BikeshedBuilderConstants.ADD_IMAGES, images)
}

function getImageSize (file: File) {
  return browserImageSize(file)
    .then(({ width, height }) => {
      return { file, width, height }
    })
}

export function removeImage (context, image: string) {
  console.warn('@TODO addImages')
}

export function preview (context, image: string) {
  console.warn('@TODO addImages')
}

Add additional bikeshed builder actions


var canvas = document.getElementById('game');
var context = canvas.getContext('2d');

var Ball = function(x, y, radius, context) {
  this.x = x;
  this.y = y;
  this.radius = radius || 10;
  this.startAngle = 0;
  this.endAngle = (Math.PI / 180) * 360;
  this.context = context
  this.speed = 0
}

Ball.prototype.draw = function () {
  context.arc(this.x, this.y, this.radius, this.startAngle, this.endAngle);
  context.fillStyle = "white"
  context.fill();
  return this;
};

Ball.prototype.move = function () {
  if (this.x < canvas.width - this.radius && this.y < canvas.height - this.radius ){
    this.x += this.speed;
    // this.y += this.speed;
  }
  return this;
};

var golfBall = new Ball(350, 450, 5, 0);

requestAnimationFrame(function gameLoop() {
  context.beginPath();
  context.clearRect(0, 0, canvas.width, canvas.height);
  context.closePath();
  golfBall.draw().move();
  requestAnimationFrame(gameLoop);
});

module.exports = Ball;

var canvas = document.getElementById('game');
var context = canvas.getContext('2d');

var Ball = function(x, y, radius, context) {
  this.x = x;
  this.y = y;
  this.radius = radius || 10;
  this.startAngle = 0;
  this.endAngle = (Math.PI * 2);
  this.context = context
  this.speed = 3
  this.xDirection = 1
  this.yDirection = 1

}

Ball.prototype.draw = function () {
  context.arc(this.x, this.y, this.radius, this.startAngle, this.endAngle);
  context.fillStyle = "white"
  context.fill();
  return this;
};

Ball.prototype.move = function () {
  this.x = this.x + (this.speed * this.xDirection);
  this.y = this.y + (this.speed * this.yDirection);

  if (this.x >= canvas.width - this.radius || this.x < 0) {
    this.xDirection *= -1;
    this.speed *= 0.8
  }
  if (this.y >= canvas.height - this.radius || this.y < 0) {
    this.yDirection *= -1;
  }
  return this;
};

var golfBall = new Ball(400, 400, 5, 0);

requestAnimationFrame(function gameLoop() {
  context.beginPath();
  context.clearRect(0, 0, canvas.width, canvas.height);
  context.closePath();
  golfBall.draw().move();
  requestAnimationFrame(gameLoop);
});

module.exports = Ball;

Add Y direction, bouncing, slowing


'use strict';

const Hoek = require('hoek');
const Config = require('./config');

exports.register = function (server, options, next) {

    Hoek.assert(server.connections.length === 1,
                'You cannot register this plugin for two connections at once. ' +
                'Register it for each connection on your server.');

    const results = Config.getConfig(options);

    if (results.error) {
        return next(results.error);
    }

    const config = results.value;

    // For simplicity
    config.meta.page.name = config.query.page.name;
    config.meta.limit.name = config.query.limit.name;

    // Sets uri for generated link
    config.uri = config.meta.baseUri || server.info.uri;

    const decorate = require('./decorate')(config);
    const ext      = require('./ext')(config);

    server.decorate('reply', config.reply.paginate, decorate.paginate);
    server.ext('onPreHandler', ext.onPreHandler);
    server.ext('onPreResponse', ext.onPreResponse);

    return next();
};

exports.register.attributes = {
    pkg: require('../package.json')
};

'use strict';

const Config = require('./config');

exports.register = function (server, options, next) {

    if(server.connections.length !== 1) {
      return next({
        name: 'ValidationError',
        details: {
          message: 'You cannot register this plugin for two connections at once. \n' +
          'Register it for each connection on your server.',
          context: server.connections
        }
      });
    }
    const results = Config.getConfig(options);

    if (results.error) {
        return next(results.error);
    }

    const config = results.value;

    // For simplicity
    config.meta.page.name = config.query.page.name;
    config.meta.limit.name = config.query.limit.name;

    // Sets uri for generated link
    config.uri = config.meta.baseUri || server.info.uri;

    const decorate = require('./decorate')(config);
    const ext      = require('./ext')(config);

    server.decorate('reply', config.reply.paginate, decorate.paginate);
    server.ext('onPreHandler', ext.onPreHandler);
    server.ext('onPreResponse', ext.onPreResponse);

    return next();
};

exports.register.attributes = {
    pkg: require('../package.json')
};

Refactor registering, replacing throw by next


var mongoose = require('mongoose');

// connect
mongoose.connect('mongodb://localhost/website', function(err) {
  if (err) { throw err; }
});

// Schema
var fileSchema = new mongoose.Schema({
    id : { type : String},
    content : String
});

// model
var fileModel = mongoose.model('files', fileSchema);

// create the file
exports.createFile = function(nameFile) {
    var newFile = new fileModel({ id : nameFile });
    newFile.content = '### Here is a sample of Markdown';

    newFile.save(function (err) {
        if (err) { throw err; }
        console.log('We successfully created ' + nameFile + " document.");
    });
}

exports.fileExists = function(nameFile, callback) {
    // console.log(nameFile);
    fileModel.find({id: nameFile}, function (err, file) {
        if (err) {
            throw err;
        }
        if (file.length == 0) {
            callback(false);
        } else {
            callback(true);
        }
    });
}

var mongoose = require('mongoose');
var fs = require('fs');

// connect
mongoose.connect('mongodb://localhost/website', function(err) {
  if (err) { throw err; }
});

// Schema
var fileSchema = new mongoose.Schema({
    id : { type : String},
    content : String
});

// model
var fileModel = mongoose.model('files', fileSchema);

// create the file
exports.createFile = function(nameFile) {
    var newFile = new fileModel({ id : nameFile });

    fs.readFile(__dirname + '/../views/markdown_template.ejs', function(err, data) {
        if (err) {
            throw err;
        }
        newFile.content = data;
        newFile.save(function (err) {
            if (err) {
                throw err;
            }
            console.log('We successfully created ' + nameFile + " document.");
        });
    });
}

exports.getFile = function(nameFile, callback) {
    fileModel.find({id: nameFile}, function (err, file) {
        if (err) {
            throw err;
        }
        if (file.length == 0) {
            callback(null);
        } else {
            callback(file[0].content);
        }
    });
}

Read template file when inserting in bdd


jQuery(document).ready(function ($) {
    $('#BuildModal').on('show.bs.modal', function (event) {
        var button = $(event.relatedTarget);
        var recipient = button.data('build');
        var modal = $(this)
        modal.find('#build-link').attr('href', recipient);
    });
});

jQuery(document).ready(function ($) {
    $('#BuildModal').on('show.bs.modal', function (event) {
        var button = $(event.relatedTarget);
        var recipient = button.data('build');
        var modal = $(this);
        modal.find('#build-link').attr('href', recipient);
    });

    $('a.device-builds, #build-link').click(function() {
        ga('send', {
            hitType: 'event',
            eventCategory: 'FxOS Builds',
            eventAction: 'click'
        });
    });

});

Send GA event on FxOS build clicks.


const crypto = require('crypto');

/**
 * memHandler - In memory upload handler
 * @param {object} options
 * @param {string} fieldname
 * @param {string} filename
 */
module.exports = function(options, fieldname, filename) {
  let buffers = [];
  let fileSize = 0; // eslint-disable-line
  let hash = crypto.createHash('md5');

  const getBuffer = () => Buffer.concat(buffers);
  const emptyFunc = () => '';

  return {
    dataHandler: function(data) {
      buffers.push(data);
      hash.update(data);
      fileSize += data.length;
      if (options.debug) {
        return console.log('Uploading %s -> %s, bytes: %d', fieldname, filename, fileSize); // eslint-disable-line
      }
    },
    getBuffer: getBuffer,
    getFilePath: emptyFunc,
    getFileSize: function(){
      return fileSize;
    },
    getHash: function(){
      return hash.digest('hex');
    },
    complete: getBuffer,
    cleanup: emptyFunc
  };
};

const crypto = require('crypto');

/**
 * memHandler - In memory upload handler
 * @param {object} options
 * @param {string} fieldname
 * @param {string} filename
 */
module.exports = function(options, fieldname, filename) {
  let buffers = [];
  let fileSize = 0; // eslint-disable-line
  let hash = crypto.createHash('md5');

  const getBuffer = () => Buffer.concat(buffers);
  const emptyFunc = () => '';

  return {
    dataHandler: function(data) {
      buffers.push(data);
      hash.update(data);
      fileSize += data.length;
      debugLog(options, `Uploading ${fieldname} -> ${filename}, bytes: ${fileSize}`);
    },
    getBuffer: getBuffer,
    getFilePath: emptyFunc,
    getFileSize: function(){
      return fileSize;
    },
    getHash: function(){
      return hash.digest('hex');
    },
    complete: getBuffer,
    cleanup: emptyFunc
  };
};

Use debug log for logging.


var nodegcm = require('node-gcm');

// insert Google Server API Key here
var Gcm = exports.Gcm = function (api_key) {
  this.sender = new nodegcm.Sender(api_key);
};

Gcm.prototype.send = function(gcmIds, data){
  var message = new nodegcm.Message();
  message.addDataWithObject(data);
  this.sender.send(message, gcmIds, 4, function (err, result) {
    console.log(result);
  });
};

var nodegcm = require('node-gcm');

// insert Google Server API Key here
var Gcm = exports.Gcm = function (api_key) {
  this.sender = new nodegcm.Sender(api_key);
};

Gcm.prototype.send = function(gcmIds, json){
	var data = json;
	if( data.MG != undefined && data.message === undefined ){
		data.message = data.MG;
	}

	if( data.UO.NM != undefined && data.title === undefined ){
		data.title = data.UO.NM;
	}

  var message = new nodegcm.Message();
  message.addDataWithObject(data);
  this.sender.send(message, gcmIds, 4, function (err, result) {
    console.log(result);
  });
};

Add GCM message & title


var xhr = require('xmlhttprequest').XMLHttpRequest;
var relative = /^https?:\/\//i;
var MyXMLHttpRequest = global.XMLHttpRequest = function() {
	xhr.apply(this, arguments);

	var oldOpen = this.open;
	this.open = function() {
		var args = Array.prototype.slice.call(arguments);
		var url = args[1];

		if(url && !relative.test(url)) {
			args[1] = MyXMLHttpRequest.base + url;
		}
		return oldOpen.apply(this, args);
	};
};

module.exports = function() {
	return function(req, res, next) {
		MyXMLHttpRequest.base = req.protocol + "://" + req.get('host');
		next();
	};
};

var xhr = require('xmlhttprequest').XMLHttpRequest;
var relative = /^https?:\/\//i;
var MyXMLHttpRequest = global.XMLHttpRequest = function() {
	xhr.apply(this, arguments);

	var oldOpen = this.open;
	this.open = function() {
		var args = Array.prototype.slice.call(arguments);
		var url = args[1];

		if(url && !relative.test(url)) {
			args[1] = MyXMLHttpRequest.base + url;
		}
		return oldOpen.apply(this, args);
	};
	// jQuery checks for this property to see if XHR supports CORS
	this.withCredentials = true;
};

module.exports = function() {
	return function(req, res, next) {
		MyXMLHttpRequest.base = req.protocol + "://" + req.get('host');
		next();
	};
};

Allow CORS support check for jQuery to pass


/**
 * Sustainable Solutions (NZ) Ltd. 2020
 * mSupply Mobile
 */

import Realm from 'realm';

export class BreachLog extends Realm.Object {}

BreachLog.schema = {
  name: 'BreachLog',
  primaryKey: 'id',
  properties: {
    id: 'string',
    temperatureLogs: { type: 'linkingObjects', objectType: 'TemperatureLog', property: 'breach' },
    startTimestamp: 'date',
    endTimestamp: 'date',
  },
};

export default BreachLog;

/**
 * Sustainable Solutions (NZ) Ltd. 2020
 * mSupply Mobile
 */

import Realm from 'realm';

export class BreachLog extends Realm.Object {}

BreachLog.schema = {
  name: 'BreachLog',
  primaryKey: 'id',
  properties: {
    id: 'string',
    temperatureLogs: { type: 'linkingObjects', objectType: 'TemperatureLog', property: 'breach' },
    startTimestamp: 'date',
    endTimestamp: { type: 'date', optional: true },
  },
};

export default BreachLog;

Add optional breach log end timestamp


'use strict'
const grunt = require('gruntfile-api')
const fs = require('fs')
const path = require('path')
const spawn = require('child_process').spawn
const gruntfile = fs.readFileSync(path.join(window.localStorage.getItem('current'), 'Gruntfile.js'))

var processes = {}

exports.getTasks = function () {
  return new Promise(function (resolve, reject) {
    grunt.init(gruntfile)
    let tasks = JSON.parse(grunt.getJsonTasks())

    let taskList = []

    for (let task in tasks) {
      taskList.push(task)
    }

    return resolve(taskList)
  })
}

exports.runTask = function (task) {
  // Stop task if running
  if (processes[task]) {
    processes[task].kill()
    return
  }

  let dir = window.localStorage.getItem('current')
  var command = spawn('grunt', [task], {cwd: dir})

  // Save
  processes[task] = command

  // Remove when done
  command.on('close', function () {
    delete processes[task]
  })
}

'use strict'
const grunt = require('gruntfile-api')
const fs = require('fs')
const path = require('path')
const spawn = require('child_process').spawn
const gruntfile = fs.readFileSync(path.join(window.localStorage.getItem('current'), 'Gruntfile.js'))

global.processes = {}

exports.getTasks = function () {
  return new Promise(function (resolve, reject) {
    grunt.init(gruntfile)
    let tasks = JSON.parse(grunt.getJsonTasks())

    let taskList = []

    for (let task in tasks) {
      taskList.push(task)
    }

    return resolve(taskList)
  })
}

exports.runTask = function (task, cb) {
  // Stop task if running
  if (global.processes[task]) {
    global.processes[task].kill()
    cb()
    return
  }

  let dir = window.localStorage.getItem('current')
  var command = spawn('grunt', [task], {cwd: dir})

  // Save
  global.processes[task] = command

  cb()

  // Remove when done
  command.on('close', function () {
    delete global.processes[task]
  })
}

Store processes in a global var


var result = {};

load('./lib/bopomofo_encoder.js');

if (!stringsAreUTF8()) {
  throw 'You need UTF-8 enabled SpiderMonkey to do cook the data.';
  quit();
}

var line;
while (line = readline()) {

  line = line.split(' ');

  if (line[1].indexOf('_punctuation_') !== -1) continue;

  var str = BopomofoEncoder.encode(line[1].replace(/\-/g, ''));

  switch (arguments[0]) {
    case 'words':
    default:
      if (str.length > 1) continue;
    break;
    case 'phrases':
      if (str.length === 1) continue;
    break;
  }

  if (!result[str]) {
    result[str] = [];
  }

  result[str].push([line[0], parseFloat(line[2])]);
}

for (syllables in result) {
  result[syllables] = result[syllables].sort(
    function(a, b) {
      return (b[1] - a[1]);
    }
  );
}

var jsonStr = JSON.stringify(result).replace(/\],/g, '],\n');

print(jsonStr);

quit(0);

var result = {};

load('./lib/bopomofo_encoder.js');

if (!stringsAreUTF8()) {
  throw 'You need UTF-8 enabled SpiderMonkey to do cook the data.';
  quit();
}

var line;
while (line = readline()) {

  line = line.split(' ');

  if (line[1].indexOf('_punctuation_') !== -1) continue;

  var str = line[1]
    .replace(/([^\u02ca\u02c7\u02cb\u02d9])(\-|$)/g, '$1 $2')
    .replace(/\-/g, '');
  str = BopomofoEncoder.encode(str);

  switch (arguments[0]) {
    case 'words':
    default:
      if (str.length > 1) continue;
    break;
    case 'phrases':
      if (str.length === 1) continue;
    break;
  }

  if (!result[str]) {
    result[str] = [];
  }

  result[str].push([line[0], parseFloat(line[2])]);
}

for (syllables in result) {
  result[syllables] = result[syllables].sort(
    function(a, b) {
      return (b[1] - a[1]);
    }
  );
}

var jsonStr = JSON.stringify(result).replace(/\],/g, '],\n');

print(jsonStr);

quit(0);

Make sure tone 1 is on record of the database