$(function() {

  var Settings = {},
    demo = new NetVis(Settings),
    SrcURL="lotr.netvis";

  $('#history').rangeslider();

  $("#reset-positions").click(demo.resetPositions);
  $("#play").click(demo.play);

  d3.json(SrcURL, function(error, json) {
  	if (error) {
  		demo.View.Logger.error("Failure loading "+SrcURL+": "+ error.statusText);
  		return;
  	}
  	demo.View.Logger.info("Succesfully resolved " + SrcURL);
    demo.parse(json);
    demo.View.Logger.info(demo);
    demo.initView();
  });
});

var demo; // define netVis object here so that it is global
// and console accessable

$(function() {

  Settings = {};
  demo = new NetVis(Settings);
  var SrcURL="lotr.netvis";

  $('#history').rangeslider();

  $("#reset-positions").click(demo.resetPositions);
  $("#play").click(demo.play);

  d3.json(SrcURL, function(error, json) {
  	if (error) {
  		demo.View.Logger.error("Failure loading "+SrcURL+": "+ error.statusText);
  		return;
  	}
  	demo.View.Logger.info("Succesfully resolved " + SrcURL);
    demo.parse(json);
    demo.View.Logger.info(demo);
    demo.initView();
  });
});

Declare netvis instance globally to access from console


const globalSetup = require("./global-setup");
const app = globalSetup.app;
const request = require("request");
const chai = require("chai");
const expect = chai.expect;

describe("port directive configuration", function () {

	this.timeout(20000);

	beforeEach(function (done) {
		app.start().then(function() { done(); } );
	});

	afterEach(function (done) {
		app.stop().then(function() { done(); });
	});

	describe("Set port 8090", function () {
		before(function() {
			// Set config sample for use in this test
			process.env.MM_CONFIG_FILE = "tests/configs/port_8090.js";
		});
		it("should return 200", function (done) {
			request.get("http://localhost:8090", function (err, res, body) {
				expect(res.statusCode).to.equal(200);
				done();
			});
		});
	});
});

const globalSetup = require("./global-setup");
const app = globalSetup.app;
const request = require("request");
const chai = require("chai");
const expect = chai.expect;

describe("port directive configuration", function () {

	this.timeout(20000);

	beforeEach(function (done) {
		app.start().then(function() { done(); } );
	});

	afterEach(function (done) {
		app.stop().then(function() { done(); });
	});

	describe("Set port 8090", function () {
		before(function() {
			// Set config sample for use in this test
			process.env.MM_CONFIG_FILE = "tests/configs/port_8090.js";
		});
		it("should return 200", function (done) {
			request.get("http://localhost:8090", function (err, res, body) {
				expect(res.statusCode).to.equal(200);
				done();
			});
		});
	});

	describe("Set port 8100 on enviroment variable MM_PORT", function () {
		before(function() {
			process.env.MM_PORT = 8100;
			// Set config sample for use in this test
			process.env.MM_CONFIG_FILE = "tests/configs/port_8090.js";
		});
		it("should return 200", function (done) {
			request.get("http://localhost:8100", function (err, res, body) {
				expect(res.statusCode).to.equal(200);
				done();
			});
		});
	});

});

Add test for check MM_PORT enviroment variable


/* global beforeEach, afterEach */

import chai from 'chai'
import sinon from 'sinon'
import sinonChai from 'sinon-chai'

import {setScheduler} from '../../src/scheduler-assignment'
import TestScheduler from './test-scheduler'

chai.use(sinonChai)
global.expect = chai.expect

beforeEach(function () {
  this.sandbox = sinon.sandbox.create()
  setScheduler(new TestScheduler())
})

afterEach(function () {
  this.sandbox.restore()
  setScheduler(null)
})

/* global beforeEach, afterEach */

import chai from 'chai'
import sinon from 'sinon'
import sinonChai from 'sinon-chai'

import {setScheduler} from '../../src/scheduler-assignment'
import TestScheduler from './test-scheduler'

chai.use(sinonChai)
global.expect = chai.expect

beforeEach(function () {
  document.body.innerHTML = ''
  this.sandbox = sinon.sandbox.create()
  setScheduler(new TestScheduler())
})

afterEach(function () {
  this.sandbox.restore()
  setScheduler(null)
})

Clear document body between tests


var uuid = require("uuid");
var Dialog = require("../dialog");

module.exports = function(apiToken, botId) {
  this.apiToken = apiToken;
  this.botId = botId;

  this.incoming = function(message) {
    var payload = {
      message: {
        conversation_distinct_id: message.chatId,
        creator_distinct_id: message.from,
        distinct_id: message.id,
        platform: 'kik',
        provider: 'kik',
        mtype: message.type,
        sent_at: message.timestamp / 1000,
        properties: {
          text: message.body
        }
      }
    };

    return Dialog.track(apiToken, botId, payload);
  },

  this.outgoing = function(message) {
    var payload = {
      message: {
        conversation_distinct_id: message.chatId,
        distinct_id: uuid.v4(),
        platform: 'kik',
        provider: 'kik',
        mtype: message.type,
        sent_at: new Date().getTime(),
        properties: {
          text: message.body
        }
      }
    };

    return Dialog.track(apiToken, botId, payload);
  }
};

var uuid = require("uuid");
var Dialog = require("../dialog");

module.exports = function(apiToken, botId) {
  this.apiToken = apiToken;
  this.botId = botId;

  this.incoming = function(message) {
    var payload = {
      message: {
        conversation_distinct_id: message.chatId,
        creator_distinct_id: message.from,
        distinct_id: message.id,
        platform: 'kik',
        provider: 'kik',
        mtype: message.type,
        sent_at: message.timestamp / 1000,
        properties: {
          text: message.body
        }
      }
    };

    return Dialog.track(apiToken, botId, payload);
  },

  this.outgoing = function(object) {
    var payload = {
      message: {
        conversation_distinct_id: object.chatId,
        distinct_id: uuid.v4(),
        platform: 'kik',
        provider: 'kik',
        mtype: object.type,
        sent_at: new Date().getTime() / 1000,
        properties: {
          text: object.body
        }
      }
    };

    return Dialog.track(apiToken, botId, payload);
  }
};

Update variable name and timestamp format


import React from 'react'
import {connect} from 'react-redux'
import {compose, lifecycle} from 'recompose'
import {Route, Switch} from "react-router"
import {ConnectedRouter} from "react-router-redux"

import auth from '../auth'
import {updateAuth} from '../actions/auth'
import PageHeader from './PageHeader'
import HomeView from "./HomeView"
import VideoView from "./VideoView"
import UserContainer from "./UserContainer"
import GroupView from "../views/GroupView"

import '../css/App.css'

const styles = {
  app: {
    minHeight: '100vh',
  },
}

const enhance = compose(
  connect(),
  lifecycle({
    componentWillMount() {
      this.unsubscribeAuth = auth.onAuthStateChanged((user) => (
        this.props.dispatch(updateAuth({user}))
      ))
    },

    componentWillUnmount() {
      this.unsubscribeAuth()
    },
  }),
)

const App = ({history}) => (
  <div style={styles.auth}>
    <PageHeader/>
    <ConnectedRouter history={history}>
      <Switch>
        <Route path='/' component={HomeView}/>
        <Route path='groups/:groupName' component={GroupView}/>
        <Route path='users/:userId' component={UserContainer}/>
        <Route path='videos/:videoId' component={VideoView}/>
        <Route component={HomeView}/>
      </Switch>
    </ConnectedRouter>
  </div>
)

export default enhance(App)

import React from 'react'
import {connect} from 'react-redux'
import {compose, lifecycle} from 'recompose'
import {Route, Switch} from "react-router"
import {ConnectedRouter} from "react-router-redux"

import auth from '../auth'
import {updateAuth} from '../actions/auth'
import PageHeader from './PageHeader'
import HomeView from "./HomeView"
import VideoView from "./VideoView"
import UserContainer from "./UserContainer"
import GroupView from "../views/GroupView"

import '../css/App.css'

const styles = {
  app: {
    minHeight: '100vh',
  },
}

const enhance = compose(
  connect(),
  lifecycle({
    componentWillMount() {
      this.unsubscribeAuth = auth.onAuthStateChanged((user) => (
        this.props.dispatch(updateAuth({user}))
      ))
    },

    componentWillUnmount() {
      this.unsubscribeAuth()
    },
  }),
)

const App = ({history}) => (

    <ConnectedRouter history={history}>

        <PageHeader/>
        <Switch>
          <Route path='/' component={HomeView}/>
          <Route path='groups/:groupName' component={GroupView}/>
          <Route path='users/:userId' component={UserContainer}/>
          <Route path='videos/:videoId' component={VideoView}/>
          <Route component={HomeView}/>
        </Switch>

    </ConnectedRouter>

)

export default enhance(App)

Remove most routes and get app to build


var _ = require('underscore');

if (typeof Array.prototype.forEach != 'function') {
    Array.prototype.forEach = function (fn, scope) {
        _.forEach(this, fn, scope);
    };
}

//source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
if (!Function.prototype.bind) {
    Function.prototype.bind = function (oThis) {
        if (typeof this !== 'function') {
            // closest thing possible to the ECMAScript 5
            // internal IsCallable function
            throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
        }

        var aArgs = Array.prototype.slice.call(arguments, 1),
            fToBind = this,
            fNOP = function () {
            },
            fBound = function () {
                return fToBind.apply(this instanceof fNOP
                        ? this
                        : oThis,
                    aArgs.concat(Array.prototype.slice.call(arguments)));
            };

        if (this.prototype) {
            // native functions don't have a prototype
            fNOP.prototype = this.prototype;
        }
        fBound.prototype = new fNOP();

        return fBound;
    };
}

var _ = require('underscore');

_.extend(Array.prototype, {
    //deprecated! -> forEach (ist auch ein JS-Standard!)
    each: function(fn, scope) {
        _.each(this, fn, scope);
    },

    //to use array.forEach directly
    forEach: function(fn, scope) {
        _.forEach(this, fn, scope);
    }
});

if (typeof Array.prototype.add != 'function') {
    //add is alias for push
    Array.prototype.add = function () {
        this.push.apply(this, arguments);
    };
}

if (typeof Array.prototype.shuffle != 'function') {
    //+ Jonas Raoni Soares Silva
    //@ http://jsfromhell.com/array/shuffle [rev. #1]
    Array.prototype.shuffle = function () {
        for (var j, x, i = this.length; i; j = parseInt(Math.random() * i), x = this[--i], this[i] = this[j], this[j] = x);
        return this;
    };
}

//source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
if (!Function.prototype.bind) {
    Function.prototype.bind = function (oThis) {
        if (typeof this !== 'function') {
            // closest thing possible to the ECMAScript 5
            // internal IsCallable function
            throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
        }

        var aArgs = Array.prototype.slice.call(arguments, 1),
            fToBind = this,
            fNOP = function () {
            },
            fBound = function () {
                return fToBind.apply(this instanceof fNOP
                        ? this
                        : oThis,
                    aArgs.concat(Array.prototype.slice.call(arguments)));
            };

        if (this.prototype) {
            // native functions don't have a prototype
            fNOP.prototype = this.prototype;
        }
        fBound.prototype = new fNOP();

        return fBound;
    };
}

Revert "set only forEach globally for Array.prototyp if not exists (ie8 fallback)"


import Vue from 'vue'

Vue.directive('fixed', {
    bind: function () {
        this.el.className += " fixedsticky";
        this.el.css()
    }
});

var vm = new Vue({
    el: 'body'
});

window.vm = vm;

import Vue from 'vue'

Vue.directive('fixed', {
    bind: function () {
        this.el.className += " fixedsticky";
        this.el.css()
    }
});

const vm = new Vue({
    el: 'body'
});

window.vm = vm;

Add basic js file for dev-section


const spawn = require('cross-spawn');

let args = process.argv.slice(2);

const server = args.indexOf('--dev') > -1
  ? null
  : require('../../examples/server');

if (args.indexOf('--config') === -1) {
  args = args.concat(['--config', 'test/e2e/nightwatch.config.js']);
}
if (args.indexOf('--env') === -1) {
  args = args.concat(['--env', 'phantomjs']);
}
const i = args.indexOf('--test');
if (i > -1) {
  args[i + 1] = `test/e2e/specs/${args[i + 1]}`;
}
if (args.indexOf('phantomjs') > -1) {
  process.env.PHANTOMJS = true;
}

const runner = spawn('./node_modules/.bin/nightwatch', args, {
  stdio: 'inherit'
});

runner.on('exit', (code) => {
  if (server) server.close();
  process.exit(code);
});

runner.on('error', (err) => {
  if (server) server.close();
  throw err;
});

const spawn = require('cross-spawn');

/* eslint-disable no-var */
var args = process.argv.slice(2);
/* eslint-enable */

const server = args.indexOf('--dev') > -1
  ? null
  : require('../../examples/server');

if (args.indexOf('--config') === -1) {
  args = args.concat(['--config', 'test/e2e/nightwatch.config.js']);
}
if (args.indexOf('--env') === -1) {
  args = args.concat(['--env', 'phantomjs']);
}
const i = args.indexOf('--test');
if (i > -1) {
  args[i + 1] = `test/e2e/specs/${args[i + 1]}`;
}
if (args.indexOf('phantomjs') > -1) {
  process.env.PHANTOMJS = true;
}

const runner = spawn('./node_modules/.bin/nightwatch', args, {
  stdio: 'inherit'
});

runner.on('exit', (code) => {
  if (server) server.close();
  process.exit(code);
});

runner.on('error', (err) => {
  if (server) server.close();
  throw err;
});

Replace let with var to fix travis build


import puppeteer from 'puppeteer';
import { toMatchImageSnapshot } from 'jest-image-snapshot';

import IMAGE_SNAPSHOT_CONFIG from 'constants/image-diff';

expect.extend({ toMatchImageSnapshot });

it('Visual regression test', async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('http://localhost:3000');
  const screenshot = await page.screenshot();

  expect(screenshot).toMatchImageSnapshot(IMAGE_SNAPSHOT_CONFIG);

  browser.close();
});

import puppeteer from 'puppeteer';
import { toMatchImageSnapshot } from 'jest-image-snapshot';

import IMAGE_SNAPSHOT_CONFIG from 'constants/image-diff';

expect.extend({ toMatchImageSnapshot });

it('Visual regression test', async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('http://localhost:3000');
  const screenshot = await page.screenshot();
  browser.close();

  expect(screenshot).toMatchImageSnapshot(IMAGE_SNAPSHOT_CONFIG);
});

Relocate code related to closing browser


var
  path = require("path");

var
  gulp = require("gulp"),
  del = require("del");

var
  config = require("../../project.config");

gulp.task("frontend-clean", false, function (cb) {
  del([
    path.join(config.dest, "**")
  ], cb);
});

var
  path = require("path");

var
  gulp = require("gulp"),
  del = require("del");

var
  config = require("../../project.config");

gulp.task("frontend-clean", false, function (cb) {
  del([
    path.join(config.dest, "/**/*")
  ], cb);
});

Clean directory contents without removing the directory


/**
  Utility Functions
  @description a collection of utility functions, aka junk drawer
  @exports {function} isCacheableRequest
**/

/**
  @name isCacheableRequest
  @desc determines if the request is cacheable based on HTTP verb used,
    will return false for actionable HTTP verbs like POST or DELETE
  @param {string} httpMethod
  @returns {boolean} result
**/
const uncacheableMethods = [ 'POST', 'PUT', 'DELETE' ];
export function isCacheableRequest(httpMethod) {
  return !!~uncacheableMethods.indexOf(httpMethod.toUpperCase());
}

/**
  @name isPromise
  @desc determines if a given value is a promise
  @param {any} potentialPromise
  @returns {boolean} result
**/
export function isPromise(potentialPromise) {
  return typeof potentialPromise.then === 'function' &&
    typeof potentialPromise['catch'] === 'function'; // eslint-disable-line
}

/**
  Utility Functions
  @description a collection of utility functions, aka junk drawer
  @exports {function} isCacheableRequest
**/

/**
  @name isCacheableRequest
  @desc determines if the request is cacheable based on HTTP verb used,
    will return false for actionable HTTP verbs like POST or DELETE
  @param {string} httpMethod
  @returns {boolean} result
**/
const uncacheableMethods = [ 'POST', 'PUT', 'DELETE' ];
export function isCacheableRequest(httpMethod) {
  return !!~uncacheableMethods.indexOf(httpMethod.toUpperCase());
}

/**
  @name isPromise
  @desc determines if a given value is a promise
  @param {any} potentialPromise
  @returns {boolean} result
**/
export function isPromise(potentialPromise) {
  return potentialPromise && typeof potentialPromise.then === 'function' &&
    typeof potentialPromise['catch'] === 'function'; // eslint-disable-line
}

Add null guard to isPromise


'use strict';

const Wit = require('node-wit').Wit;
const myActions = require('./my-wit-actions');

/**
 * Handles wit.ai integration
 * @param event
 */
const init = event => new Promise((resolveMessage, rejectMessage) => {
  if (event.sender && event.sender.id && event.message && event.message.text) {
    const sessionId = `${event.id}-${event.updated}`;
    const context0 = {};
    const actions = {
      send: (request, response) => new Promise(() => {
        resolveMessage(response);
      })
    };
    // Copy custom actions to actions
    Object.keys(myActions).map((value) => {
      actions[value] = myActions[value];
    });
    const client = new Wit({
      accessToken: process.env.WIT_AI_TOKEN,
      actions: actions
    });
    client.runActions(sessionId, event.message.text, context0)
    .then(result => resolveMessage(result))
    .catch(error => rejectMessage(error));
  } else {
    rejectMessage('wit ai failed');
  }
});

module.exports = init;

'use strict';

const Wit = require('node-wit').Wit;
const myActions = require('./my-wit-actions');

/**
 * Handles wit.ai integration
 * @param event
 */
const init = event => new Promise((resolveMessage, rejectMessage) => {
  if (event.sender && event.sender.id && event.message && event.message.text) {
    const sessionId = `${event.id}-${event.updated}`;
    const context0 = {};
    const actions = {
      send: (request, response) => new Promise(() => {
        resolveMessage(response);
      }),
      debugContext: (data) => new Promise((resolve, reject) => {
        const context = data.context;
        console.log('WIT.AI DEBUG:')
        console.log(JSON.stringify(data, null, 2));
        resolve(context);
      })
    };
    // Copy custom actions to actions
    Object.keys(myActions).map((value) => {
      actions[value] = myActions[value];
    });
    const client = new Wit({
      accessToken: process.env.WIT_AI_TOKEN,
      actions: actions
    });
    client.runActions(sessionId, event.message.text, context0)
    .then(result => resolveMessage(result))
    .catch(error => rejectMessage(error));
  } else {
    rejectMessage('wit ai failed');
  }
});

module.exports = init;

Add debugContext action for wit.ai


var nest = require('depnest')
var { h, when, send } = require('mutant')

exports.gives = nest('channel.html.subscribeToggle')
exports.needs = nest({
  'intl.sync.i18n': 'first',
  'keys.sync.id': 'first',
  'message.async.publish': 'first',
  'channel.obs.subscribed': 'first'
})

exports.create = function (api) {
  var i18n = api.intl.sync.i18n
  return nest('channel.html.subscribeToggle', function (channel, opts) {
    var yourId = api.keys.sync.id()
    var subscribedChannels = api.channel.obs.subscribed(yourId)

    return when(subscribedChannels.has(channel),
      h('a.ToggleButton.-unsubscribe', {
        'href': '#',
        'title': i18n('Click to unsubscribe'),
        'ev-click': send(unsubscribe, channel)
      }, i18n('Subscribed')),
      h('a.ToggleButton.-subscribe', {
        'href': '#',
        'ev-click': send(subscribe, channel)
      }, i18n('Subscribe'))
    )
  })

  function subscribe (id) {
    // confirm
    api.message.async.publish({
      type: 'channel',
      channel: id,
      subscribed: true
    })
  }

  function unsubscribe (id) {
    // confirm
    api.message.async.publish({
      type: 'channel',
      channel: id,
      subscribed: false
    })
  }
}

var nest = require('depnest')
var { h, when, send } = require('mutant')

exports.gives = nest('channel.html.subscribeToggle')
exports.needs = nest({
  'intl.sync.i18n': 'first',
  'keys.sync.id': 'first',
  'message.async.publish': 'first',
  'channel.obs.subscribed': 'first'
})

exports.create = function (api) {
  var i18n = api.intl.sync.i18n
  return nest('channel.html.subscribeToggle', function (channel, opts) {
    var yourId = api.keys.sync.id()
    var subscribedChannels = api.channel.obs.subscribed(yourId)

    return when(subscribedChannels.has(channel),
      h('a.ToggleButton.-unsubscribe', {
        'href': '#',
        'title': i18n('Click to unsubscribe'),
        'ev-click': send(unsubscribe, channel)
      }, i18n('Unsubscribe')),
      h('a.ToggleButton.-subscribe', {
        'href': '#',
        'ev-click': send(subscribe, channel)
      }, i18n('Subscribe'))
    )
  })

  function subscribe (id) {
    // confirm
    api.message.async.publish({
      type: 'channel',
      channel: id,
      subscribed: true
    })
  }

  function unsubscribe (id) {
    // confirm
    api.message.async.publish({
      type: 'channel',
      channel: id,
      subscribed: false
    })
  }
}

Change 'Subscribed' button text to 'Unsubscribe'


/*global describe, beforeEach, it*/
'use strict';

var path    = require('path');
var helpers = require('yeoman-generator').test;

describe('digitaria generator', function () {
    beforeEach(function (done) {
        helpers.testDirectory(path.join(__dirname, 'temp'), function (err) {
            if (err) {
                return done(err);
            }

            this.app = helpers.createGenerator('digitaria:app', [
                '../../app'
            ]);
            done();
        }.bind(this));
    });

    it('creates expected files', function (done) {
        var expected = [
            // add files you expect to exist here.
            '.jshintrc',
            '.editorconfig'
        ];

        helpers.mockPrompt(this.app, {
            'someOption': true
        });
        this.app.options['skip-install'] = true;
        this.app.run({}, function () {
            helpers.assertFiles(expected);
            done();
        });
    });
});

/*global describe, beforeEach, it*/
'use strict';

var path    = require('path');
var helpers = require('yeoman-generator').test;

describe('digitaria generator', function () {
    beforeEach(function (done) {
        helpers.testDirectory(path.join(__dirname, 'temp'), function (err) {
            if (err) {
                return done(err);
            }

            this.app = helpers.createGenerator('digitaria:app', [
                '../../app'
            ]);
            done();
        }.bind(this));
    });

    it('creates expected files', function (done) {
        var expected = [
            // add files you expect to exist here.
            '.jshintrc',
            '.editorconfig'
        ];

        helpers.mockPrompt(this.app, {
            'name': 'Hello World',
            'version': '0.1.0',
            'repository': '',
            'projectType': 'isDrupal',
            'libs': [ 'hasModernizr', 'hasUniform', 'hasHandlebars' ]
        });
        this.app.options['skip-install'] = true;
        this.app.run({}, function () {
            helpers.assertFiles(expected);
            done();
        });
    });
});

Update generator tests for travis-cli


export const INTRODUCTION = '1. Introduction';
export const PRIMITIVES = '2. Primitives';
export const FOUNDATION = '3. Foundation';
export const LOW_LEVEL_BLOCKS = '4. Low level blocks';
export const MID_LEVEL_BLOCKS = '5. Mid level blocks';
export const COMPOSITIONS = '6. Compositions';
export const PLAYGROUND = '7. Playground';

export const addStoryInGroup = (groupTitle, storyTitle) => `${groupTitle} / ${storyTitle}`;

export const INTRODUCTION = '1. Introduction';
export const PRIMITIVES = '2. Primitives';
export const FOUNDATION = '3. Foundation';
export const LOW_LEVEL_BLOCKS = '4. Low level blocks';
export const MID_LEVEL_BLOCKS = '5. Mid level blocks';
export const COMPOSITIONS = '6. Compositions';
export const MARKETING = '7. Marketing';
export const PLAYGROUND = '8. Playground';

export const addStoryInGroup = (groupTitle, storyTitle) => `${groupTitle} / ${storyTitle}`;

Add Marketing section in Storybook


/*!
 * Start Bootstrap - Agency Bootstrap Theme (http://startbootstrap.com)
 * Code licensed under the Apache License v2.0.
 * For details, see http://www.apache.org/licenses/LICENSE-2.0.
 */

// jQuery for page scrolling feature - requires jQuery Easing plugin
$(function() {
    $('a.page-scroll').bind('click', function(event) {
        var $anchor = $(this);
        $('html, body').stop().animate({
            scrollTop: $($anchor.attr('href')).offset().top
        }, 1500, 'easeInOutExpo');
        event.preventDefault();
    });
});

// Highlight the top nav as scrolling occurs
$('body').scrollspy({
    target: '.navbar-fixed-top'
})

// Closes the Responsive Menu on Menu Item Click
$('.navbar-collapse ul li a').click(function() {
    $('.navbar-toggle:visible').click();
});

/*!
 * Start Bootstrap - Agency Bootstrap Theme (http://startbootstrap.com)
 * Code licensed under the Apache License v2.0.
 * For details, see http://www.apache.org/licenses/LICENSE-2.0.
 */

// jQuery for page scrolling feature - requires jQuery Easing plugin
$(function() {
    $('a.page-scroll').bind('click', function(event) {
        var $anchor = $(this);
        $('html, body').stop().animate({
            scrollTop: $($anchor.attr('href')).offset().top
        }, 1500, 'easeInOutExpo');
        $(anchor.attr('href')).focus();
        event.preventDefault();
    });
});

// Highlight the top nav as scrolling occurs
$('body').scrollspy({
    target: '.navbar-fixed-top'
})

// Closes the Responsive Menu on Menu Item Click
$('.navbar-collapse ul li a').click(function() {
    $('.navbar-toggle:visible').click();
});

Fix a problem where scrolling wouldn't work for screen reader users.


import select from 'select-dom';
import {h} from 'dom-chef';

import * as icons from '../libs/icons';
import {getRepoURL} from '../libs/page-detect';

export default async () => {
	const comments = select.all('.timeline-comment-header:not(.rgh-timestamp-tree-link)');

	for (const comment of comments) {
		const timestampEl = select('relative-time', comment);
		const timestamp = timestampEl.attributes.datetime.value;
		const href = `/${getRepoURL()}/tree/HEAD@{${timestamp}}`;

		timestampEl.parentNode.after(
			<span>

				<a
					href={href}
					class="timeline-comment-action btn-link rgh-timestamp-button tooltipped tooltipped-n rgh-tooltipped"
					aria-label="View repo at the time of this comment"
					>
					{icons.code()}
				</a>
			</span>
		);

		comment.classList.add('rgh-timestamp-tree-link');
	}
};

import select from 'select-dom';
import {h} from 'dom-chef';

import * as icons from '../libs/icons';
import {getRepoURL} from '../libs/page-detect';

export default async () => {
	const comments = select.all('.timeline-comment-header:not(.rgh-timestamp-tree-link)');

	for (const comment of comments) {
		const timestampEl = select('relative-time', comment);
		const timestamp = timestampEl.attributes.datetime.value;
		const href = `/${getRepoURL()}/tree/HEAD@{${timestamp}}`;

		timestampEl.parentNode.after(
			' ',
			<a
				href={href}
				class="timeline-comment-action btn-link rgh-timestamp-button tooltipped tooltipped-n rgh-tooltipped"
				aria-label="View repo at the time of this comment"
				>
				{icons.code()}
			</a>
		);

		comment.classList.add('rgh-timestamp-tree-link');
	}
};

Drop unnecessary wrapper element in time-machine-links


(function (arr, i) {
  // Broken out into a separate function to avoid deoptimizations due to the try/catch for the
  // array iterator case.
  function sliceIterator() {
    // this is an expanded form of `for...of` that properly supports abrupt completions of
    // iterators etc. variable names have been minimised to reduce the size of this massive
    // helper. sometimes spec compliancy is annoying :(
    //
    // _n = _iteratorNormalCompletion
    // _d = _didIteratorError
    // _e = _iteratorError
    // _i = _iterator
    // _s = _step

    var _arr = [];
    var _n = true;
    var _d = false;
    var _e = undefined;
    try {
      for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
        _arr.push(_s.value);
        if (i && _arr.length === i) break;
      }
    } catch (err) {
      _d = true;
      _e = err;
    } finally {
      try {
        if (!_n && _i["return"]) _i["return"]();
      } finally {
        if (_d) throw _e;
      }
    }
    return _arr;
  }

  if (Array.isArray(arr)) {
    return arr;
  } else if (Symbol.iterator in Object(arr)) {
    return sliceIterator();
  } else {
    throw new TypeError("Invalid attempt to destructure non-iterable instance");
  }
});

(function () {
  // Broken out into a separate function to avoid deoptimizations due to the try/catch for the
  // array iterator case.
  function sliceIterator(arr, i) {
    // this is an expanded form of `for...of` that properly supports abrupt completions of
    // iterators etc. variable names have been minimised to reduce the size of this massive
    // helper. sometimes spec compliancy is annoying :(
    //
    // _n = _iteratorNormalCompletion
    // _d = _didIteratorError
    // _e = _iteratorError
    // _i = _iterator
    // _s = _step

    var _arr = [];
    var _n = true;
    var _d = false;
    var _e = undefined;
    try {
      for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
        _arr.push(_s.value);
        if (i && _arr.length === i) break;
      }
    } catch (err) {
      _d = true;
      _e = err;
    } finally {
      try {
        if (!_n && _i["return"]) _i["return"]();
      } finally {
        if (_d) throw _e;
      }
    }
    return _arr;
  }

  return function (arr, i) {
    if (Array.isArray(arr)) {
      return arr;
    } else if (Symbol.iterator in Object(arr)) {
      return sliceIterator(arr, i);
    } else {
      throw new TypeError("Invalid attempt to destructure non-iterable instance");
    }
  };
})();

Move slice iterator helper out of primary call


const path = require('path');

module.exports = {
  entry: {
    main: './src/js/index.js',
  },
  output: {
    path: path.resolve(__dirname, './lib'),
    filename: 'ReactWeather.js',
    libraryTarget: 'umd',
    library: 'ReactWeather',
    umdNamedDefine: true,
  },
  devtool: false,
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /(node_modules)/,
        loader: 'babel-loader',
      },
    ],
  },
  externals: {
    react: 'react',
    'react-dom': 'react-dom',
  },
  plugins: [],
};

const path = require('path');

module.exports = {
  entry: {
    main: './src/js/index.js',
  },
  output: {
    path: path.resolve(__dirname, './lib'),
    filename: 'ReactWeather.js',
    libraryTarget: 'umd',
    library: 'ReactWeather',
    umdNamedDefine: true,
    globalObject: 'this'
  },
  devtool: false,
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /(node_modules)/,
        loader: 'babel-loader',
      },
    ],
  },
  externals: {
    react: 'react',
    'react-dom': 'react-dom',
  },
  plugins: [],
};

Use this as a globalObject in webpack


import DCOSStore from './stores/DCOSStore';
import ResourceTableUtil from './utils/ResourceTableUtil';
import RoutingService from './routing';

module.exports = {
  DCOSStore,
  ResourceTableUtil,
  RoutingService
};

import DCOSStore from './stores/DCOSStore';
import ResourceTableUtil from './utils/ResourceTableUtil';
import RoutingService from './routing';
import NavigationService from './navigation';

module.exports = {
  DCOSStore,
  ResourceTableUtil,
  RoutingService,
  NavigationService
};

Add navigation service to the plugin sdk


var _ = require('lodash');

var periods = require('./periods');
var PRESTATIONS = require('../prestations');

module.exports = function reverseMap(openFiscaFamille, date, injectedRessources) {
    var period = periods.map(date);

    // Don't show prestations that have been injected by the user, and not calculated by the simulator
    _.forEach(injectedRessources, function(resource) {
        delete PRESTATIONS[resource];
    });

    return _.mapValues(PRESTATIONS, function(format, prestationName) {
        var type = format.type,
            computedPrestation = openFiscaFamille[prestationName],
            result = computedPrestation[period];

        var uncomputabilityReason = openFiscaFamille[prestationName + '_non_calculable'] && openFiscaFamille[prestationName + '_non_calculable'][period];

        if (uncomputabilityReason) {
            return uncomputabilityReason;
        }

        if (format.montantAnnuel) {
            result *= 12;
        }

        if (type == Number) {
            result = Number(result.toFixed(2));
        }

        return result;
    });
};

var _ = require('lodash');

var periods = require('./periods');
var PRESTATIONS = require('../prestations');

module.exports = function reverseMap(openFiscaFamille, date, injectedRessources) {
    var period = periods.map(date);
    var prestationsToDisplay = _.cloneDeep(PRESTATIONS);

    // Don't show prestations that have been injected by the user, and not calculated by the simulator
    _.forEach(injectedRessources, function(resource) {
        delete prestationsToDisplay[resource];
    });

    return _.mapValues(prestationsToDisplay, function(format, prestationName) {
        var type = format.type,
            computedPrestation = openFiscaFamille[prestationName],
            result = computedPrestation[period];

        var uncomputabilityReason = openFiscaFamille[prestationName + '_non_calculable'] && openFiscaFamille[prestationName + '_non_calculable'][period];

        if (uncomputabilityReason) {
            return uncomputabilityReason;
        }

        if (format.montantAnnuel) {
            result *= 12;
        }

        if (type == Number) {
            result = Number(result.toFixed(2));
        }

        return result;
    });
};

Fix bug about not displaying injected prestations


var genericLoader = require('./generic_report_loader');

var AGGREGATION_STEPS = [
  { $project: { instanceId: 1, date: 1, active: 1, _id: 0 } },
  { $group: { _id: "$instanceId",  activityDates: { $push: { date: "$date", active: "$active" } } } },
  { $project: {  instanceId: "$_id",  _id: 0, activityDates: 1 } }
];

function wrapResults(results) {
  return {
    stats: results
  };
}

module.exports = {
  load: function instancesPerDay(db) {
    return genericLoader.makeMongoAggregation(db, AGGREGATION_STEPS).then(wrapResults);
  }
};

var genericLoader = require('./generic_report_loader');

var AGGREGATION_STEPS = [
  { $project: { instanceId: 1, date: 1, active: 1, _id: 0 } },
  { $group: { _id: "$instanceId",  activityDates: { $push: { date: "$date", active: "$active" } } } },
  { $project: {  instanceId: "$_id",  _id: 0, activityDates: 1 } }
];

function wrapResults(results) {
  return {
    stats: results
  };
}

// sort by date of first run
function sortByAppearDate(results) {
  return results.sort(function(a,b) {
    return b.activityDates[0].date.getTime() - a.activityDates[0].date.getTime();
  });
}

module.exports = {
  load: function instancesPerDay(db) {
    return genericLoader.makeMongoAggregation(db, AGGREGATION_STEPS).then(sortByAppearDate).then(wrapResults);
  }
};

Sort lifetime chart data by date of first run


var EventEmitter = require('events').EventEmitter;
try {
    var midi = require('./build/Release/midi_addon');
} catch(e) {
    try {
        var midi = require('./build/default/midi_addon');
    } catch(e2) {
        console.log(e);
        throw(e2);
    }
}
midi.input.prototype.__proto__ = EventEmitter.prototype;
module.exports = midi;

// Node version 0.4.0 and 0.6.0 compatibility
try {
  var midi = require('./build/Release/midi_addon');
} catch(e) { try {
  var midi = require('./build/default/midi_addon');
} catch(e) {
  throw e;
}}

// MIDI input inherits from EventEmitter
var EventEmitter = require('events').EventEmitter;
midi.input.prototype.__proto__ = EventEmitter.prototype;

module.exports = midi;

TIdy up main script file and add comments.


import Phaser from 'phaser';

import { tile, nextTile, alignToGrid, pixelToTile } from '../../tiles';
import { clone } from '../../utils';

import tween from './tween';

export default class extends Phaser.Sprite {
  constructor(game, x, y, sprite, frame, id, objectType) {
    const alignedCoords = alignToGrid({ x, y });

    x = alignedCoords.x;
    y = alignedCoords.y;

    super(game, x, y, sprite, frame);

    this.anchor.setTo(0.5, 0.5);

    // use a bunch of different properties to hopefully achieve a unique id
    this.id = id || this.key + this.frame + this.x + this.y + (Math.floor(Math.random() * 100) + 1);

    this.objectType = objectType || 'generic';

    this.timers = [];

    this.tile = {};

    this.setTile();
  }

  move(nextPixelCoord, callback) {
    this.moving = true;

    tween.call(this, nextPixelCoord, 35, function() {
      this.moving = false;

      this.setTile();

      if (callback) callback.call(this);
    });
  }

  setTile() {
    this.tile = tile.call(this);
  }

  destroy() {
    super.destroy();

    this.destroyed = true;
  }
}

import Phaser from 'phaser';

import { tile, nextTile, alignToGrid, pixelToTile } from '../../tiles';
import { clone } from '../../utils';

import tween from './tween';

export default class extends Phaser.Image {
  constructor(game, x, y, sprite, frame, id, objectType) {
    const alignedCoords = alignToGrid({ x, y });

    x = alignedCoords.x;
    y = alignedCoords.y;

    super(game, x, y, sprite, frame);

    this.anchor.setTo(0.5, 0.5);

    // use a bunch of different properties to hopefully achieve a unique id
    this.id = id || this.key + this.frame + this.x + this.y + (Math.floor(Math.random() * 100) + 1);

    this.objectType = objectType || 'generic';

    this.timers = [];

    this.tile = {};

    this.setTile();
  }

  move(nextPixelCoord, callback) {
    this.moving = true;

    tween.call(this, nextPixelCoord, 35, function() {
      this.moving = false;

      this.setTile();

      if (callback) callback.call(this);
    });
  }

  setTile() {
    this.tile = tile.call(this);
  }

  destroy() {
    super.destroy();

    this.destroyed = true;
  }
}

Extend from image instead of sprite


/* Helper function for creating point objects
 *
 * Each point has fields x & y hodling coordinates
 */
function point(x, y) {
	return {x: x, y: y};
}

// Stores all created nodes, indexed by their unique 2-letter keys
var nodes = {};

/* Return a new node object & add it to list of nodes
 *
 * name: character's full name
 * key: character's 2-letter key
 * neighbors: list of connected characters' 2-letter keys
 * pos: object containing fields x & y representing center of node's circle
 */
function newNode(name, key, neighbors, pos) {
	var node = {
		name: name,
		key: key,
		neighbors: neighbors,
		pos: pos
	};
	nodes[key] = node;

	// TODO: draw the node

	return node;
}

/* Helper function for creating point objects
 *
 * Each point has fields x & y hodling coordinates
 */
function point(x, y) {
	return {x: x, y: y};
}

// Position of top-left node
var TOP_LEFT = point(50, 50);
var WIDTH = 100;

// Stores all created nodes, indexed by their unique 2-letter keys
var nodes = {};

/* Return a new node object & add it to list of nodes
 *
 * name: character's full name
 * key: character's 2-letter key
 * neighbors: list of connected characters' 2-letter keys
 * pos: object containing fields x & y representing center of node's circle
 */
function newNode(name, key, neighbors, pos) {
	var node = {
		name: name,
		key: key,
		neighbors: neighbors,
		pos: pos
	};
	nodes[key] = node;

	// TODO: draw the node

	return node;
}

Define vars TOP_LEFT & WIDTH


( function( $, d, undefined )
{
    d._ = window.console.debug.bind( window.console );

    var m = new d.Manager();

    m.initialize( function()
    {
        var v = new d.View( $( '#bookmarks' ), m );

        v.display();
    } );

} )( Zepto, this.Dashboard );

( function( $, d, undefined )
{

    d._ = window.console.debug.bind( window.console );

    d.init = function()
    {
        d.initFontSize();
        d.initManager();
    };

    d.initManager = function()
    {
        this.manager = new d.Manager();

        this.manager.initialize( this.initView.bind( this ) );
    };

    d.initFontSize = ( function()
    {
        var $sizes = $( '#fontSize > a' );

        return function()
        {
            if( localStorage.fontSize )
            {
                document.body.className = localStorage.fontSize;

                $sizes.removeClass( 'selected' );
                $sizes.parent().find( 'a[data-size="' + localStorage.fontSize + '"]' ).addClass( 'selected' );
            }

            $sizes.bind( 'click', function( e )
            {
                var $this = $( e.target );

                $this.siblings().removeClass( 'selected' );
                $this.addClass( 'selected' );

                document.body.className = localStorage.fontSize = $this.attr( 'data-size' );
            } );
        }
    } )();

    d.initView = function()
    {
        this.view = new d.View( $( '#bookmarks' ), this.manager );

        this.view.display();
    };

    d.init();

} )( Zepto, this.Dashboard );

Implement the font size selector.


/*jshint es5:true */
define(function (require, exports, module) {
  var playlist = require("text!../playlist.json");
  // TODO: we need wraparound for the case that we run out of tracks
  var currentTrack = playlist.pop();
  var audio = new Audio();

  function playUrl(url) {
    function canplay() {
      audio.removeEventListener("canplay", canplay);
      audio.play();
    }

    audio.addEventListener("canplay", canplay);
    audio.src = url;
  }

  // When the current track ends, start another
  audio.addEventListener("ended", function() {
    currentTrack = playlist.pop();
    if(!currentTrack) {
      // TODO: No more trackS! We should bubble up error handling to UI somehow...
      console.error("[brackets-wavelength] No more tracks");
      return;
    }
    playUrl(currentTrack.url);
  });

  return {
    play: function() {
      if(!audio.src) {
        playUrl(currentTrack.url);
      } else {
        audio.play();
      }
    },
    pause: function() {
      audio.pause();
    },
    get paused() {
      return audio.paused;
    },
    get trackInfo() {
      return currentTrack;
    }
  };
});

Remove es5 option to make travis happy


module.exports = function () {
    var browser = require('openurl');
    var config = require('./config');
    var REDIRECT_URI = 'https://rogeriopvl.github.com/downstagram';

    console.log('\n********** DOWNSTAGRAM OAUTH SETUP **********');
    console.log('\n To use downstagram you need to authorize it to access your instagram account.');
    console.log('Your browser will open for you to authorize the app...');

    var authURI = [
        'https://instagram.com/oauth/authorize/?',
        'client_id=' + config.auth.client_id,
        '&redirect_uri=' + REDIRECT_URI,
        '&response_type=token'
    ].join('');

    browser.open(authURI);

    console.log('Now according to the intructions in the App page, insert your access token here:');

    var stdin = process.openStdin();
    stdin.on('data', function(chunk) {
        var token = chunk.toString().trim();
        config.auth.access_token = token;
        config.save(config.auth);
        process.exit(0);
    });
};

module.exports = function () {
    var browser = require('openurl');
    var config = require('./config');
    var REDIRECT_URI = 'https://rogeriopvl.github.com/downstagram';

    console.log('\n********** DOWNSTAGRAM OAUTH SETUP **********');
    console.log('\n To use downstagram you need to authorize it to access your instagram account.');
    console.log('Your browser will open for you to authorize the app...');

    var authURI = [
        'https://instagram.com/oauth/authorize/?',
        'client_id=' + config.auth.client_id,
        '&redirect_uri=' + REDIRECT_URI,
        '&response_type=token'
    ].join('');

    try {
        browser.open(authURI);
    } catch (e) {
        console.log('Could not open browser. Maybe you are on a headless server?');
        console.log('Open a web browser on this URL to continue: ', authURI);
    }

    console.log('Now according to the intructions in the App page, insert your access token here:');

    var stdin = process.openStdin();
    stdin.on('data', function(chunk) {
        var token = chunk.toString().trim();
        config.auth.access_token = token;
        config.save(config.auth);
        process.exit(0);
    });
};

Add alternative to browser opening on headless servers


import React, { Component } from 'react';
import Channel from 'jschannel';

const CHANNEL_NOT_READY = 'CHANNEL_NOT_READY';

class Seed extends Component {

  componentWillUnmount() {
    this.iframe.removeEventListener('load', this.iframeLoaded);
    this.channel.destroy();
  }

  request = (requestOptions, callback) => {
    return new Promise((resolve, reject) => {
      if (this.state.ready !== true)
        return reject(new Error(CHANNEL_NOT_READY));

      this.channel.call({
        method: 'httpRequest',
        params: requestOptions,
        success: resolve,
        error: reject
      });
    });
  }

  iframeLoaded = () => {
    this.channel = Channel.build({
      window: this.iframe.contentWindow,
      origin: this.props.baseUrl,
      scope: this.props.scope,
      onReady: () => {
        this.setState({ ready: true });
        this.props.onReady && this.props.onReady();
      }
    });
  }

  render() {
    return (
      <iframe
        src={this.props.baseUrl}
        height="0"
        width="0"
        frameBorder="0"
        sandbox="allow-scripts allow-same-origin"
        ref={(iframe) => { if (iframe) { this.iframe = iframe; iframe.addEventListener('load', this.iframeLoaded, false); } } }
        >
      </iframe>
    );
  }
}

Seed.propTypes = {
  baseUrl: React.PropTypes.string,
  scope: React.PropTypes.string,
  onReady: React.PropTypes.func
};

export default Seed;

import React, { Component } from 'react';
import Channel from 'jschannel';

const CHANNEL_NOT_READY = 'CHANNEL_NOT_READY';

class Seed extends Component {

  componentWillUnmount() {
    this.iframe.removeEventListener('load', this.iframeLoaded);
    this.channel.destroy();
  }

  request = (requestOptions, callback) => {
    return new Promise((resolve, reject) => {
      if (!this.state || this.state.ready !== true)
        return reject(new Error(CHANNEL_NOT_READY));

      this.channel.call({
        method: 'httpRequest',
        params: requestOptions,
        success: resolve,
        error: reject
      });
    });
  }

  iframeLoaded = () => {
    this.channel = Channel.build({
      window: this.iframe.contentWindow,
      origin: this.props.baseUrl,
      scope: this.props.scope,
      onReady: () => {
        this.setState({ ready: true });
        this.props.onReady && this.props.onReady();
      }
    });
  }

  render() {
    return (
      <iframe
        src={this.props.baseUrl}
        height="0"
        width="0"
        frameBorder="0"
        sandbox="allow-scripts allow-same-origin"
        ref={(iframe) => { if (iframe) { this.iframe = iframe; iframe.addEventListener('load', this.iframeLoaded, false); } } }
        >
      </iframe>
    );
  }
}

Seed.propTypes = {
  baseUrl: React.PropTypes.string,
  scope: React.PropTypes.string,
  onReady: React.PropTypes.func
};

export default Seed;

Check for state presence as well


describe('googleGrecaptcha provider', function (){
  beforeEach(module('noCAPTCHA'));

  var googleGrecaptcha;

  beforeEach(inject(function (_googleGrecaptcha_){
    googleGrecaptcha = _googleGrecaptcha_;
  }));

  describe('return promise', function (){
    it('should resolve promise', function (done){
      googleGrecaptcha.then(function (){
        done();
      });
    });
  });
});

describe('googleGrecaptcha provider', function (){
  beforeEach(module('noCAPTCHA'));

  var googleGrecaptcha;
  var $document;

  describe('default options', function (){
    beforeEach(function(){
      inject(function (_googleGrecaptcha_, _$document_){
        $document = _$document_;
        googleGrecaptcha = _googleGrecaptcha_;
      });
    });

    it('should add script element with correct url', function (){
      expect($document.find('body').html()).to.contain('<script src="https://www.google.com/recaptcha/api.js?onload=recaptchaOnloadCallback&render=explicit"></script>');
    });

    it('should resolve promise', function (done){
      googleGrecaptcha.then(function (){
        done();
      });
    });
  });

  describe('with specific language', function (){
    beforeEach(function(){
      module(function(googleGrecaptchaProvider){
        googleGrecaptchaProvider.setLanguage('fi');
      });

      inject(function (_googleGrecaptcha_, _$document_){
        $document = _$document_;
        googleGrecaptcha = _googleGrecaptcha_;
      });
    });

    it('should add script element with correct url', function (){
      expect($document.find('body').html()).to.contain('<script src="https://www.google.com/recaptcha/api.js?onload=recaptchaOnloadCallback&render=explicit&hl=fi"></script>')
    });
  });
});

Test correct script elements are appended to body


'use babel';

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

/**
 * Gets first root folder opened in Atom
 *
 * @todo Support multiple root folders etc.
 */
exports.getRootFolder = () => atom.project.getPaths()[0];

/**
 * Returns true if current project is RN
 */
exports.isRNProject = () => {
  const rootFolder = exports.getRootFolder();
  return fs.existsSync(path.join(rootFolder, 'node_modules', 'react-native'));
};

'use babel';

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

/**
 * Gets first root folder opened in Atom
 *
 * @todo Support multiple root folders etc.
 */
exports.getRootFolder = () => atom.project.getPaths()[0];

/**
 * Returns true if current project is RN
 */
exports.isRNProject = () => {
  const rootFolder = exports.getRootFolder();
  if (!rootFolder) return false;
  return fs.existsSync(path.join(rootFolder, 'node_modules', 'react-native'));
};

Fix crash when no project opened


export const MiniMongo = {}

if (global.Mongo) {
  MiniMongo.Collection = class MiniMongoCollection extends global.Mongo.Collection {
    constructor(name) {
      super(null)   // null causes this to be a MiniMongo
      this.collectionName = name
    }

    _ensureIndex() {
      // Don't do anything but don't throw as MiniMongo normally would
      // REVISIT: if this was ever used on the client it should throw still
    }
  }
}

export const MiniMongo = {}

const NAME_TO_CAUSE_MINIMONGO = null

if (global.Mongo) {
  MiniMongo.Collection = class MiniMongoCollection extends global.Mongo.Collection {
    constructor(name) {
      super(NAME_TO_CAUSE_MINIMONGO)
      this._name = name   // eslint-disable-line no-underscore-dangle
      this.indexes = []
    }

    _ensureIndex(keys, options) {
      this.indexes.push({ keys, options })
      // MiniMongo would normally throw an exception but we ignore it
      // If this was ever used on the client it should throw still
    }
  }
}

Switch to _name for MiniMongo.Collection name to mimick production, store indexes created


'use strict';

var items = require('../data/items');
var express = require('express');
var router = express.Router();

var data = {
    title: 'Football Peek - The quickest access to football results',
    description: 'Access football results, tables, top scorers and top assists from the major leagues and competitions',
    items: items
};

router.route('/')
    .get((req, res) => {
        res.render('pages/home', data);
    });

module.exports = router;

'use strict';

var items = require('../data/items');
var config = require('../config');
var helper = require('../helper');
var express = require('express');
var router = express.Router();

var data = {
    title: 'Football Peek - The quickest access to football results',
    description: 'Access football results, tables, top scorers and top assists from the major leagues and competitions',
    items: items
};

router.route('/').get((req, res) => {
    getResults();

    res.render('pages/home', data);
});

function getResults() {
    var dates = getHandledDates();

    // items.forEach(item => {
    //     var resultsData = helper.readJsonFile(helper.stringFormat(config.paths.resultsData, item.code, config.periods.current));
    //     console.log(resultsData);
    // });

    // var resultsData = helper.readJsonFile(helper.stringFormat(config.paths.resultsData, items[0].code, config.periods.current));

    // resultsData.forEach(result => {
    //     result.matches.forEach((matche) => {
    //         console.log(matche.date);
    //     });
    // });
}

function getHandledDates() {
    var dates = [];
    var currentDate = new Date();
    var limitDate = 8;

    for (var i = limitDate; i >= 1; i--) {
        dates.push(getFormattedDate(new Date(new Date().setDate(currentDate.getDate() - i))));
    }

    dates.push(getFormattedDate(new Date(new Date().setDate(currentDate.getDate()))));

    for (var i = 1; i <= limitDate; i++) {
        dates.push(getFormattedDate(new Date(new Date().setDate(currentDate.getDate() + i))));
    }

    return dates;
}

function getFormattedDate(date) {
    var dd = date.getDate();
    var mm = date.getMonth() + 1;
    var yyyy = date.getFullYear();

    dd = dd < 10 ? '0' + dd : dd;
    mm = mm < 10 ? '0' + mm : mm;

    return dd + '/' + mm + '/' + yyyy;
}

module.exports = router;

Add basics to get last results


'use strict';

module.exports = function(resizerOptions) {
	function resizer(client) {
		window.iFrameResizer = {
			targetOrigin: client._targetOrigin
		};

		if (resizerOptions) {
			for (var nextKey in resizerOptions) {
				// Avoid bugs when hasOwnProperty is shadowed
				if (Object.prototype.hasOwnProperty.call(resizerOptions, nextKey)) {
					window.iFrameResizer[nextKey] = resizerOptions[nextKey];
				}
			}
		}

		require('iframe-resizer/js/iframeResizer.contentWindow');
	}
	return resizer;
};

'use strict';

module.exports = function(resizerOptions) {
	function resizer(client) {
		window.iFrameResizer = {
			targetOrigin: client._targetOrigin
		};

		if (resizerOptions) {
			for (var nextKey in resizerOptions) {
				// Avoid bugs when hasOwnProperty is shadowed
				if (Object.prototype.hasOwnProperty.call(resizerOptions, nextKey)) {
					window.iFrameResizer[nextKey] = resizerOptions[nextKey];
				}
			}
		}

		var resizerContentWindow = document.createElement('script');
		resizerContentWindow.src = 'https://s.brightspace.com/lib/iframe-resizer/3.6.5/iframeResizer.contentWindow.js';
		document.head.appendChild(resizerContentWindow);
	}
	return resizer;
};

Insert iframe-resizer content window js script instead of requiring


// temporary script to show message about Random renamed to Volatile on trading page

pjax_config_page('trading', function(){
    return {
        onLoad: function() {
            var tempMsgKey = 'hide_temp_msg';
            if (SessionStore.get(tempMsgKey)) {
                $('#temp_notice_msg').addClass('invisible');
            }

            $('#close_temp_msg').click(function() {
                SessionStore.set(tempMsgKey, '1');
                $('#temp_notice_msg').addClass('invisible');
            });
        }
    };

});

// temporary script to show message about Random renamed to Volatile on trading page

pjax_config_page('trading', function(){
    return {
        onLoad: function() {
            var hasRandom = false;
            Object.keys(Symbols.markets())
                .forEach(function(s) {
                    if (s === 'random') {
                        hasRandom = true;
                    }
                });

            var tempMsgKey = 'hide_temp_msg';
            if (SessionStore.get(tempMsgKey) || !hasRandom) {
                $('#temp_notice_msg').addClass('invisible');
            }

            $('#close_temp_msg').click(function() {
                SessionStore.set(tempMsgKey, '1');
                $('#temp_notice_msg').addClass('invisible');
            });
        }
    };

});

Hide msg when no random market


'use strict';

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

module.exports = function(env, callback) {
  const environments = env.config.environments || {};
  const environment = environments[env.mode] || {};
  const plugins = environment.plugins || [];

  _.merge(env.config, environment);

  async.forEachSeries(plugins, env.loadPluginModule.bind(env), callback);
};

'use strict';

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

module.exports = function(env, callback) {
  if (!env.config.environments) {
    return callback(new Error('environments must be defined.'));
  }

  const environment = env.config.environments[env.mode] || {};
  const plugins = environment.plugins || [];

  _.merge(env.config, environment);

  async.forEachSeries(plugins, env.loadPluginModule.bind(env), callback);
};

Raise error when plugin is not configured


import path from 'path';

export default (platform, env, appName) => {
  switch (platform) {
    case 'darwin': {
      return path.join(env['HOME'], 'Library', 'Application Support', appName, 'Logs');
    }
    case 'win32': {
      return path.join(env['APPDATA'], appName, 'Logs');
    }
  }
};

import path from 'path';

export default (platform, env, appName) => {
  switch (platform) {
    case 'darwin': {
      return path.join(env['HOME'], 'Library', 'Application Support', appName, 'Logs');
    }
    case 'win32': {
      return path.join(env['APPDATA'], appName, 'Logs');
    }
    case 'linux': {
      return path.join(env['HOME'], '.config', appName, 'Logs');
    }
    default: {
      console.log('Unsupported platform');
      process.exit(1);
    }
  }
};

Add linux support for logger


import React, { PropTypes } from "react"
import { Link } from "phenomic"
import Svg from "react-svg-inline"

import twitterSvg from "../icons/iconmonstr-twitter-1.svg"
import gitHubSvg from "../icons/iconmonstr-github-1.svg"

import styles from "./index.css"

const Header = (props, { metadata: { pkg } }) => (

        <Link
          className={ styles.link }
          to="/"
        >
          { "Home" }
        </Link>

        {
          pkg.twitter &&
          <a
            href={ `https://twitter.com/${pkg.twitter}` }
            className={ styles.link }
          >
            <Svg svg={ twitterSvg } cleanup />
            { "Twitter" }

        }
        {
          pkg.repository &&

            <Svg svg={ gitHubSvg } cleanup />
            { "GitHub" }

        }

)

Header.contextTypes = {
  metadata: PropTypes.object.isRequired,
}

export default Header

import React, { PropTypes } from "react"
import { Link } from "phenomic"
import Svg from "react-svg-inline"

import twitterSvg from "../icons/iconmonstr-twitter-1.svg"
import gitHubSvg from "../icons/iconmonstr-github-1.svg"

import styles from "./index.css"

const Header = (props, { metadata: { pkg } }) => (

        <Link
          className={ styles.link }
          to={ "" }
        >
          { "Home" }
        </Link>

        {
          pkg.twitter &&
          <a
            href={ `https://twitter.com/${pkg.twitter}` }
            className={ styles.link }
          >
            <Svg svg={ twitterSvg } cleanup />
            { "Twitter" }

        }
        {
          pkg.repository &&

            <Svg svg={ gitHubSvg } cleanup />
            { "GitHub" }

        }

)

Header.contextTypes = {
  metadata: PropTypes.object.isRequired,
}

export default Header

Fix base theme homepage link


/**
 * index.js - delish
 *
 * Licened under MIT license.
 * Copyright (C) 2017 Karim Alibhai.
 */

const path = require('path')
    , express = require('express')
    , app = express()
    , http = require('http').createServer(app)
    , io = require('socket.io')(http)

app.use(require('morgan')('dev'))
app.use(express.static(path.join(__dirname, 'public')))

io.on('connection', sock => {
  sock.on('data', data => {
    console.warn(data)
  })
})

http.listen(process.env.PORT || 8080, () =>
  console.log('Listening :%s', http.address().port)
)

/**
 * index.js - delish
 *
 * Licened under MIT license.
 * Copyright (C) 2017 Karim Alibhai.
 */

const path = require('path')
    , express = require('express')
    , app = express()
    , http = require('http').createServer(app)
    , io = require('socket.io')(http)

app.use(require('morgan')('dev'))
app.use(express.static(path.join(__dirname, '..', 'public')))

io.on('connection', sock => {
  sock.on('data', data => {
    console.warn(data)
  })
})

http.listen(process.env.PORT || 8080, () =>
  console.log('Listening :%s', http.address().port)
)

Fix static directory path in server


var parser   = require(__dirname+"/../lib/parser.js").parser.parse;
var compiler = require(__dirname+"/../lib/compiler.js").compiler;
var _ = require("./vendor/underscore");

function Bluemold(input, data){
  try {
    var parsed   = parser(input);
        compiled = compiler(parsed);

    _.extend(this,data);
    this._ = _;
    this.Bluemold = Bluemold;

    return (new Function("return "+compiled))();
  } catch (e) {
    return e;
  }
}

exports.Bluemold = Bluemold;

var parser   = require(__dirname+"/../lib/parser.js").parser.parse;
var compiler = require(__dirname+"/../lib/compiler.js").compiler;
var _ = require("./vendor/underscore");
var vm = require("vm");

function Bluemold(input, data){
  try {
    var parsed   = parser(input);
        compiled = compiler(parsed);

    _.extend(this,data);
    this._ = _;
    this.Bluemold = Bluemold;
    return vm.runInThisContext("try{"+compiled+"}catch(e){throw e}", "template.js")
  } catch (e) {
    e.compiled = compiled;
    return e;
  }
}

exports.Bluemold = Bluemold;

Use vm.runInThisContext for executing the template


/**
 * IsSsh
 * Checks if an input value is a ssh url or not.
 *
 * @name IsSsh
 * @function
 * @param {String} input The input url.
 * @return {Boolean} `true` if the input is a ssh url, `false` otherwise.
 */
function IsSsh(input) {

    if (typeof input !== "string") {
        return false;
    }

    var index = input.indexOf("://")
      , protocol = input.substring(0, index).split("+")
      ;

    input = input.substring(index + 3);

    if (protocol.indexOf("ssh") !== -1 || protocol.indexOf("rsync") !== -1) {
        return true;
    }

    // TODO This probably could be improved :)
    return input.indexOf("@") < input.indexOf(":");
}

module.exports = IsSsh;

// Dependencies
var Protocols = require("protocols");

/**
 * IsSsh
 * Checks if an input value is a ssh url or not.
 *
 * @name IsSsh
 * @function
 * @param {String} input The input url.
 * @return {Boolean} `true` if the input is a ssh url, `false` otherwise.
 */
function IsSsh(input) {

    if (typeof input !== "string") {
        return false;
    }

    var protocols = Protocols(input);
    input = input.substring(input.indexOf("://") + 3);
    if (protocols.indexOf("ssh") !== -1 || protocols.indexOf("rsync") !== -1) {
        return true;
    }

    // TODO This probably could be improved :)
    return input.indexOf("@") < input.indexOf(":");
}

module.exports = IsSsh;

Use protocols to parse the protocols


// Store a reference to the global setTimeout,
// in case it gets replaced (e.g. sinon.useFakeTimers())
const cachedSetTimeout = setTimeout;

function createSleepPromise(timeout, { useCachedSetTimeout } = {}) {
    const timeoutFunction = useCachedSetTimeout ? cachedSetTimeout : setTimeout;

    return new Promise((resolve) => {
        timeoutFunction(resolve, timeout);
    });
}

export default function sleep(timeout, { useCachedSetTimeout } = {}) {
    const sleepPromise = createSleepPromise(timeout, { useCachedSetTimeout });

    // Pass value through, if used in a promise chain
    function promiseFunction(value) {
        return sleepPromise.then(() => value);
    }

    // Normal promise
    promiseFunction.then = (...args) => sleepPromise.then(...args);
    promiseFunction.catch = Promise.resolve().catch;

    return promiseFunction;
}

// Store a reference to the global setTimeout,
// in case it gets replaced (e.g. sinon.useFakeTimers())
const cachedSetTimeout = setTimeout;

function createSleepPromise(timeout, { useCachedSetTimeout }) {
    const timeoutFunction = useCachedSetTimeout ? cachedSetTimeout : setTimeout;

    return new Promise((resolve) => {
        timeoutFunction(resolve, timeout);
    });
}

export default function sleep(timeout, { useCachedSetTimeout } = {}) {
    const sleepPromise = createSleepPromise(timeout, { useCachedSetTimeout });

    // Pass value through, if used in a promise chain
    function promiseFunction(value) {
        return sleepPromise.then(() => value);
    }

    // Normal promise
    promiseFunction.then = (...args) => sleepPromise.then(...args);
    promiseFunction.catch = Promise.resolve().catch;

    return promiseFunction;
}

Remove default value for createSleepPromise options


// This module exists to help determine the
// status of a network device / service.

'use strict';

function isOn() {

    // This function is designed to return true if all
    // given arguments indicate the intention is for
    // something to be enabled / on / true, etc.

    const choices = [
        true,
        'true',
        'yes',
        'on',
        'enabled'
    ];

    let result = true;

    const len = arguments.length;
    for (let i = 0; i < len; i = i + 1) {
        let arg = arguments[i];
        if (arg && typeof arg.toLowerCase === 'function') {
            arg = arg.toLowerCase();
        }
        if (choices.indexOf(arg) < 0) {
            return false;
        }
    }

    return result;
}

module.exports = isOn;

// This module exists to help determine the
// status of a network device / service.

'use strict';

function isOn(input) {

    const onValues = [
        true,
        'true',
        'yes',
        'on',
        'enabled'
    ];

    if (input && typeof input.toLowerCase === 'function') {
        input = input.toLowerCase();
    }

    return onValues.includes(input);
}

module.exports = isOn;

Remove unused functionality from isOn detector.


var _ = require('lodash');
var builder = require('xmlbuilder');

var utils = require('./utils');
var generate = require('./generate');
var parse = require('./parse');

function XMLSchema(schema) {
    this.schema = schema;
}

// Create a xml string from a schema
XMLSchema.prototype.generate = function(value, options) {
    options = _.defaults(options || {}, {
        version: '1.0',
        encoding: 'UTF-8',
        standalone: false,
        pretty: false
    });

    var xml = builder.create(this.schema.tag, {
        version: options.version,
        encoding: options.encoding,
        standalone: options.standalone
    });

    generate.applySchema(xml, this.schema, value || {});

    return xml.end({
        pretty: options.pretty
    });
};

// Parse a xml tring
XMLSchema.prototype.parse = function(xml) {
    return parse.applySchema(xml, this.schema);
};

module.exports = XMLSchema;

var _ = require('lodash');
var builder = require('xmlbuilder');

var utils = require('./utils');
var generate = require('./generate');
var parse = require('./parse');

function XMLSchema(schema) {
    this.schema = schema;
}

// Create a xml string from a schema
XMLSchema.prototype.generate = function(value, options, doctype) {
    options = _.defaults(options || {}, {
        version: '1.0',
        encoding: 'UTF-8',
        standalone: false,
        pretty: false
    });

    var xml = builder.create(this.schema.tag, {
        version: options.version,
        encoding: options.encoding,
        standalone: options.standalone
    }, doctype);

    generate.applySchema(xml, this.schema, value || {});

    return xml.end({
        pretty: options.pretty
    });
};

// Parse a xml tring
XMLSchema.prototype.parse = function(xml) {
    return parse.applySchema(xml, this.schema);
};

module.exports = XMLSchema;

Add argument to generation to create doctype


var fs = require('fs');

var storage = [];

module.exports = {
  init: (config, callback) => {
    var directories = fs.readdirSync('.');
    if (directories.indexOf(config.directory) === -1) {
      fs.mkdirSync(config.directory);
      config.documents.forEach(name => {
        fs.writeFileSync(`${config.directory}/${name}.db`, '{}');
      });
      return 'done';
    }
    config.documents.forEach(name => {
      var file = fs.readFileSync(`${config.directory}/${name}.db`);
      if (file) {
        storage[name] = new Map();
        file = JSON.parse(file);
        Object.keys(file).forEach((key) => {
          storage[name].set(key, file[key]);
        });
      } else {
        fs.writeFileSync(`${config.directory}/${name}.db`, '{}');
      }
    });
    return 'test';
  },
  get: (document, key) => {
    return storage[document].get(key);
  }
};

var fs = require('fs');

var storage = [];

module.exports = {
  init: (config, callback) => {
    var directories = fs.readdirSync('.');
    if (directories.indexOf(config.directory) === -1) {
      fs.mkdirSync(config.directory);
      config.documents.forEach(name => {
        fs.writeFileSync(`${config.directory}/${name}.db`, '');
        storage[name] = new Map();
      });
      return true;
    }
    config.documents.forEach(name => {
      if (!fs.existsSync(`${config.directory}/${name}.db`)) {
        fs.writeFileSync(`${config.directory}/${name}.db`, '');
      }
      var file = fs.readFileSync(`${config.directory}/${name}.db`);
      storage[name] = new Map(file);
    });
    setInterval(() => {
      //console.log('----');
      //console.log(storage);
      storage.forEach((document) => {
        console.log('document');
        // fs.writeFileSync(`${config.directory}/${}.db`);
      });
    }, 1000);
    return true;
  },
  get: (document, key) => {
    return storage[document].get(key);
  },
  set: (document, key, value) => {
    storage[document].set(key, value);
    return true;
  }
};

Fix crash on start when documents doesn't exists


/* jshint -W040 */
'use strict';

var path    = require('path'),
    through = require('through');

module.exports = sourcemapify;

/**
 * Transforms the browserify sourcemap
 *
 * @param browserify
 * @param options
 */
function sourcemapify(browserify, options) {
  options = options || browserify._options || {};

  // Create a stream to transform the sourcemap
  var transformStream = through(write, end);

  function write(data) {
    if (options.base) {
      // Determine the relative path
      // from the bundle file's directory to the source file
      var base = path.resolve(process.cwd(), options.base);
      data.sourceFile = path.relative(base, data.file);
    }

    if (options.root) {
      // Prepend the root path to the file path
      data.sourceFile = path.join(options.root, data.sourceFile);
    }

    this.queue(data);
  }

  function end() {
    this.queue(null);
  }

  // Add our transform stream to Browserify's "debug" pipeline
  // https://github.com/substack/node-browserify#bpipeline
  browserify.pipeline.get('debug').push(transformStream);
  return this;
}

/* jshint -W040 */
'use strict';

var path    = require('path'),
  through = require('through');

module.exports = sourcemapify;

/**
 * Transforms the browserify sourcemap
 *
 * @param browserify
 * @param options
 */
function sourcemapify(browserify, options) {
  options = options || browserify._options || {};

  function write(data) {
    if (options.base) {
      // Determine the relative path
      // from the bundle file's directory to the source file
      var base = path.resolve(process.cwd(), options.base);
      data.sourceFile = path.relative(base, data.file);
    }

    if (options.root) {
      // Prepend the root path to the file path
      data.sourceFile = path.join(options.root, data.sourceFile);
    }

    this.queue(data);
  }

  // Add our transform stream to Browserify's "debug" pipeline
  // https://github.com/substack/node-browserify#bpipeline
  configurePipeline();
  browserify.on('reset', function(){
    configurePipeline();
  });

  function configurePipeline() {
    browserify.pipeline.get('debug').push(new through(write));
  }

  return this;
}

Support for Watchify. We hook onto the pipeline on every reset and a new through object gets created.


// Dependencies
var wkeypress = require("./keypress");

/**
 * init
 *
 * @name init
 * @function
 * @return {undefined}
 */
exports.init = function () {
    var conf = this._config;
    var self = this;
    (conf.shortcuts = conf.shortcuts || []).forEach(function (c) {
        wkeypress(c.k, c.c, function (e) {
            var foo = E.path(c.f, [window, self]);
            if (typeof foo === "function") {
                foo.call(self, c.args);
            }
        });
    });
};

// Dependencies
var wkeypress = require("./wkeypress");

/**
 * init
 *
 * @name init
 * @function
 * @return {undefined}
 */
exports.init = function () {
    var conf = this._config;
    var self = this;
    (conf.shortcuts = conf.shortcuts || []).forEach(function (c) {
        wkeypress(c.k, c.c, function (e) {
            var foo = E.path(c.f, [window, self]);
            if (typeof foo === "function") {
                foo.apply(self, c.args);
            }
        });
    });
};

Use apply instead of call.


/*global JSON */

"use strict";

var request = require("request");

function rCall(command, args, callback, options) {
    var opts = options || {},
        url,
        method = args ? "POST" : "GET";

    opts.server = opts.server || "http://localhost:5307";
    opts.root = opts.root || "/ocpu";

    url = opts.server + opts.root + command;

    request({
        method: method,
        uri: url,
        body: JSON.stringify(args),
        headers: {"Content-Type": "application/json"}
    }, function (err, response, data) {
        err = err || (response && (response.statusCode === 400 ||
                        response.statusCode === 502 ||
                        response.statusCode === 503) && response.statusCode);
        if (!err) {
            if (/json$/.test(url)) {
                data = JSON.parse(data);
            }
            if (/\/ocpu\/tmp/.test(data)) {
                data = data.match("/ocpu/tmp/([a-z0-9]*)/")[1];
            }
        }
        callback(err, data);
    });
}
exports.rCall = rCall;

"use strict";

const { request } = require("./util");

function rCall(command, args, callback, {
    server = "http://localhost:5307",
    root = "/ocpu"
} = {}) {
    const method = args ? "POST" : "GET";
    const url = server + root + command;

    request({
        url,
        method,
        body: args
    }, (err, response, data) => {
        const myErr = err || (response && (response.statusCode === 400 ||
            response.statusCode === 502 || response.statusCode === 503) &&
            response.statusCode);

        let myData = data;

        if (!myErr) {
            if (/json$/.test(url)) {
                myData = JSON.parse(data);
            }
            if (/\/ocpu\/tmp/.test(data)) {
                myData = data.match("/ocpu/tmp/([a-z0-9]*)/")[1];
            }
        }
        callback(myErr, myData);
    });
}
exports.rCall = rCall;

Use custom request and update to ES2015.


"use strict";
var
  CPP = new (require('childprocess-promise')),
  RedisProto = require('redis-proto'),
  SupportedEvents = null;

class Worker{
  constructor(Socket){
    this.Socket = Socket;
    this.Levels = 0;
    Socket.on('data', Worker.OnData.bind(this));
  }
  static OnData(Buffer){
    Buffer = Buffer.toString();
    let Result = RedisProto.Decode(Buffer);
    if(!Result || !Result.length || SupportedEvents.indexOf(Result[0]) === -1){
      this.Socket.write(`-ERR unknown command '${Result[0] || ''}'\r\n`);
    } else {
      CPP.Request(Result.shift(), Result).then(function(Response){
        if(!(Response instanceof Array) && Response !== null && typeof Response === 'object'){
          if(Response.Type === 'Error') {
            Response = '-' + Response.Message;
          } else if(Response.Type === 'OK'){
            Response = '+OK';
          } else {
            Response = '';
          }
        } else {
          Response = RedisProto.Encode(Response);
        }
        if(Response === ''){
          Response = '$0\r\n';
        }
        this.Socket.write(Response + "\r\n");
      }.bind(this));
    }
  }
}

process.on('message', function(C, Instance){
  if(C !== 'Server') return ;
  Instance.on('connection', function (Socket){
    new Worker(Socket);
  });
});
CPP.once('SupportedEvents', function(Events){
  SupportedEvents = Events;
});

"use strict";
var
  CPP = new (require('childprocess-promise')),
  RedisProto = require('redis-proto'),
  SupportedEvents = null;

class Worker{
  constructor(Socket){
    this.Socket = Socket;
    this.Levels = 0;
    Socket.on('data', Worker.OnData.bind(this));
  }
  static OnData(Buffer){
    Buffer = Buffer.toString();
    let Result = RedisProto.Decode(Buffer);
    if(!Result || !Result.length || SupportedEvents.indexOf(Result[0]) === -1){
      this.Socket.write(`-ERR unknown command '${Result && Result[0] || ''}'\r\n`);
    } else {
      CPP.Request(Result.shift(), Result).then(function(Response){
        if(!(Response instanceof Array) && Response !== null && typeof Response === 'object'){
          if(Response.Type === 'Error') {
            Response = '-' + Response.Message;
          } else if(Response.Type === 'OK'){
            Response = '+OK';
          } else {
            Response = '';
          }
        } else {
          Response = RedisProto.Encode(Response);
        }
        if(Response === ''){
          Response = '$0\r\n';
        }
        this.Socket.write(Response + "\r\n");
      }.bind(this));
    }
  }
}

process.on('message', function(C, Instance){
  if(C !== 'Server') return ;
  Instance.on('connection', function (Socket){
    new Worker(Socket);
  });
});
CPP.once('SupportedEvents', function(Events){
  SupportedEvents = Events;
});

Fix a crash on invalid request


var basicAuth = require('basic-auth');

/**
 * Simple basic auth middleware for use with Express 4.x.
 *
 * Based on template found at: http://www.danielstjules.com/2014/08/03/basic-auth-with-express-4/
 *
 * @example
 * app.use('/api-requiring-auth', utils.basicAuth('username', 'password'));
 *
 * @param   {string}   username Expected username
 * @param   {string}   password Expected password
 * @returns {function} Express 4 middleware requiring the given credentials
 */
exports.basicAuth = function(username, password) {
	return function(req, res, next) {

		if (!username || !password) {
			console.log('Username or password is not set.');
			return res.send('Error: username or password not set. See guidance for setting these.');
		}

		var user = basicAuth(req);

		if (!user || user.name !== username || user.pass !== password) {
			res.set('WWW-Authenticate', 'Basic realm=Authorization Required');
			return res.send(401);
		}

		next();
	};
};

var basicAuth = require('basic-auth');

/**
 * Simple basic auth middleware for use with Express 4.x.
 *
 * Based on template found at: http://www.danielstjules.com/2014/08/03/basic-auth-with-express-4/
 *
 * @example
 * app.use('/api-requiring-auth', utils.basicAuth('username', 'password'));
 *
 * @param   {string}   username Expected username
 * @param   {string}   password Expected password
 * @returns {function} Express 4 middleware requiring the given credentials
 */
exports.basicAuth = function(username, password) {
	return function(req, res, next) {

		if (!username || !password) {
			console.log('Username or password is not set.');
			return res.send('
Error:

Username or password not set. See guidance for setting these.
');
		}

		var user = basicAuth(req);

		if (!user || user.name !== username || user.pass !== password) {
			res.set('WWW-Authenticate', 'Basic realm=Authorization Required');
			return res.sendStatus(401);
		}

		next();
	};
};

Improve error message and use correct status


const h = require('virtual-dom/h');

module.exports = function (data) {
  const {gameID, game} = data;
  return h('div', {className: 'room'}, [
    game.playing ? h('meta', {httpEquiv: 'refresh', content: '1'}) : h('form', {method: 'post', action: `/${gameID}`}, [
      h('button', {type: 'button', id: 'min'}, '-'),
      h('input', {type: 'number', name: 'max-score', min: '1', value: game.maxScore}),
      h('button', {type: 'button', id: 'max'}, '+'),
      h('button', {type: 'submit'}, 'Start')
    ]),
    h('a', {href: '/new-player/' + gameID}, 'Wanna play along?'),
    h('div', {id: 'players'}, [
      h('ul', Object.keys(game.players).map(playerID => {
        const player = game.players[playerID];
        return h('li', {
          style: {
            backgroundColor: `rgb(${player.color[1]}, ${player.color[0]}, ${player.color[2]})`
          },
          dataPlayerId: playerID
        }, 'Score: ' + player.score)
      }))
    ])
  ]);
};

const h = require('virtual-dom/h');

module.exports = function (data) {
  const {gameID, game} = data;
  return h('div', {className: 'room'}, [
    game.playing ? null : h('form', {method: 'post', action: `/${gameID}`}, [
      h('button', {type: 'button', id: 'min'}, '-'),
      h('input', {type: 'number', name: 'max-score', min: '1', value: game.maxScore}),
      h('button', {type: 'button', id: 'max'}, '+'),
      h('button', {type: 'submit'}, 'Start')
    ]),
    h('a', {href: '/new-player/' + gameID}, 'Wanna play along?'),
    h('div', {id: 'players'}, [
      h('ul', Object.keys(game.players).map(playerID => {
        const player = game.players[playerID];
        return h('li', {
          style: {
            backgroundColor: `rgb(${player.color[1]}, ${player.color[0]}, ${player.color[2]})`
          },
          dataPlayerId: playerID
        }, 'Score: ' + player.score)
      }))
    ])
  ]);
};

Add meta refresh in wrapper instead of vdom


/**
 * Receives a camel or pascal cased string, hyphenates it and makes it lowercase.
 * E.g.  myString -> my-string,   MyString -> my-string
 * @param {string} str The string to hyphenate.
 * @returns A hyphenated string in lowercase.
 */
function hyphenate (str) {
    return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
}

/**
 * Transforms a camelCased string into PascalCase.
 * @param {string} str A camelCased string.
 * @returns A PascalCased string.
 */
function pascalCase(str) {
    return str.slice(0, 1).toUpperCase() + str.substr(1);
}

module.exports = {
    hyphenate: hyphenate,
    pascalCase: pascalCase
};

const path = require('path');
const findRoot = require('find-root');

/**
 * Receives a camel or pascal cased string, hyphenates it and makes it lowercase.
 * E.g.  myString -> my-string,   MyString -> my-string
 * @param {string} str The string to hyphenate.
 * @returns A hyphenated string in lowercase.
 */
function hyphenate(str) {
    return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
}

/**
 * Transforms a camelCased string into PascalCase.
 * @param {string} str A camelCased string.
 * @returns A PascalCased string.
 */
function pascalCase(str) {
    return str.slice(0, 1).toUpperCase() + str.substr(1);
}

/**
 * Checks if a string is in hyphenated format.
 * @param {string} str A string to check.
 * @returns True if the string is in hyphenated-syntax.
 */
function isHyphenated(str) {
    return /(-)+/g.test(str);
}

/**
 * Gets the package.json file.
 * @returns A package.json object.
 */
function getPkg() {
    var root = findRoot(process.cwd());
    return require(path.join(root, 'package.json'));
}

/**
 * Gets the application name.
 * @returns A string with the application name in hyphenated syntax.
 */
function getAppName() {
    return getPkg().name;
}

module.exports = {
    hyphenate: hyphenate,
    pascalCase: pascalCase,
    isHyphenated: isHyphenated,
    getAppName: getAppName
};

Add utility to get app name based on package.json


'use strict';

// Production specific configuration
// ==================================
var production = {
    server: {
        staticDir : '/../../dist'
    },

    // MongoDB connection options
    mongodb: {
        uri: 'mongodb://localhost/devnews-dev'
    },

    seedDB: false
};

// if OPENSHIFT env variables are present, use the available connection info:
if (process.env.MONGOLAB_URI) {
    production.mongodb.uri = process.env.MONGOLAB_URI;
} else if(process.env.OPENSHIFT_MONGODB_DB_PASSWORD) {
    production.mongodb.uri = 'mongodb://' + process.env.OPENSHIFT_MONGODB_DB_USERNAME + ':' +
    process.env.OPENSHIFT_MONGODB_DB_PASSWORD + '@' +
    process.env.OPENSHIFT_MONGODB_DB_HOST + ':' +
    process.env.OPENSHIFT_MONGODB_DB_PORT + '/' +
    process.env.OPENSHIFT_APP_NAME;
}

module.exports = production;

'use strict';

// Production specific configuration
// ==================================
var production = {
    server: {
        staticDir : '/../../dist'
    },

    // MongoDB connection options
    mongodb: {
        uri: 'mongodb://localhost/devnews-dev'
    },

    seedDB: false
};

if (process.env.INIT_DB) {
    production.seedDB = true;
}

// if OPENSHIFT env variables are present, use the available connection info:
if (process.env.MONGOLAB_URI) {
    production.mongodb.uri = process.env.MONGOLAB_URI;
} else if(process.env.OPENSHIFT_MONGODB_DB_PASSWORD) {
    production.mongodb.uri = 'mongodb://' + process.env.OPENSHIFT_MONGODB_DB_USERNAME + ':' +
    process.env.OPENSHIFT_MONGODB_DB_PASSWORD + '@' +
    process.env.OPENSHIFT_MONGODB_DB_HOST + ':' +
    process.env.OPENSHIFT_MONGODB_DB_PORT + '/' +
    process.env.OPENSHIFT_APP_NAME;
}

module.exports = production;

Allow init DB via env variable


var childProcess = require('child_process'),
    fs = require('fs'),
    path = require('path'),
      dirname = path.dirname;

module.exports = {
  currentBranch: function(path, callback) {
    childProcess.exec('git symbolic-ref -q HEAD', {cwd: path}, function(err, stdout) {
      var currentBranch = stdout.split('\n')
          .filter(function(branch) { return branch; })
          .map(function(branch) { return branch.replace(/^refs\/heads\//, ''); })[0];
      callback(err, currentBranch);
    });
  },

  generate: function(configSource, output, callback) {
    fs.readFile(configSource, function(err, data) {
      if (err) {
        return callback(err);
      }

      data = JSON.parse(data);
      data.release = true;

      module.exports.currentBranch(dirname(configSource), function(err, branch) {
        if (err) {
          return callback(err);
        }

        data.name += '-' + branch.replace(/^release\//, '');
        fs.writeFile(output, JSON.stringify(data, undefined, 2), callback);
      });
    });
  }
};

var childProcess = require('child_process'),
    fs = require('fs'),
    path = require('path'),
      dirname = path.dirname;

module.exports = {
  currentBranch: function(path, callback) {
    childProcess.exec('git symbolic-ref -q HEAD', {cwd: path}, function(err, stdout) {
      var currentBranch = stdout.split('\n')
          .filter(function(branch) { return branch; })
          .map(function(branch) { return branch.replace(/^refs\/heads\//, ''); })[0];
      callback(err, currentBranch);
    });
  },

  generate: function(configSource, output, callback) {
    fs.readFile(configSource, function(err, data) {
      if (err) {
        return callback(err);
      }

      data = JSON.parse(data);
      data.release = true;

      module.exports.currentBranch(dirname(configSource), function(err, branch) {
        if (err) {
          return callback(err);
        }

        // Copy over the index source file.
        try {
          var index = fs.readFileSync(dirname(configSource) + '/index.js');
          fs.writeFileSync(dirname(output) + '/index.js', index);
        } catch (err) {
          return callback(err);
        }

        data.name += '-' + branch.replace(/^release\//, '');
        fs.writeFile(output, JSON.stringify(data, undefined, 2), callback);
      });
    });
  }
};

Copy index.js on package generation


import Ember from 'ember';

export default Ember.TextField.extend({
  type: 'file',
  attributeBindings: ['name'],
  classNames: ['hidden'],

  change: function(evt) {
    var input = evt.target;
    if (input.files && input.files[0]) {
      return this.sendAction('action', input.files[0]);
    }
  }
});

import Ember from 'ember';

export default Ember.TextField.extend({
  type: 'file',
  attributeBindings: ['name'],
  classNames: ['hidden'],
  file: null,

  change: function(evt) {
    var input = evt.target;
    if (input.files && input.files[0]) {
      // Update bindings
      var reader = new FileReader();
      reader.onload = (e) => Ember.run(() => this.set('file', e.target.result));
      reader.readAsDataURL(input.files[0]);

      // Send action
      this.sendAction('action', input.files[0]);
    }
  }
});

Add ability to bind with FileUpload view


import React from 'react';
import PropTypes from 'prop-types';
import withRoot from '../utils/withRoot';
import Head from 'next/head';
import OnlyFormFrame from '../components/OnlyFormFrame';
import SignUpForm from '../components/SignUpForm';

function PageSignUp(props) {
  return (
    <OnlyFormFrame>
      <Head>
        <title>Criar conta - OliMAT</title>
      </Head>
      <SignUpForm />
    </OnlyFormFrame>
  );
};

PageSignUp.propTypes = {
  classes: PropTypes.object.isRequired,
};

export default withRoot(PageSignUp);

import React from 'react';
import withRoot from '../utils/withRoot';
import Head from 'next/head';
import OnlyFormFrame from '../components/OnlyFormFrame';
import SignUpForm from '../components/SignUpForm';

function PageSignUp(props) {
  return (
    <OnlyFormFrame>
      <Head>
        <title>Criar conta - OliMAT</title>
      </Head>
      <SignUpForm />
    </OnlyFormFrame>
  );
};

export default withRoot(PageSignUp);

Remove unnecessary PropTypes from PageSignUp


let username = ""
const init = () => {
  console.log("Starting...");

  chrome.alarms.create("checkmessages", {
    periodInMinutes: 1
  })

  console.log("Alarm created!");

  chrome.storage.sync.get(["username"], (v) => { username = v["username"] });

  console.log("Username fetched!");
}

init()

chrome.alarms.onAlarm.addListener(a => {
  console.log("Alarm recieved.");
  if (a.name === "checkmessages") {
    console.log("Check recieved.");
    if (username !== "") {
      console.log("Checking messages...");
      fetch(`https://api.scratch.mit.edu/proxy/users/${username}/activity/count`).then(r => r.json()).then(({msg_count}) => {
        if (msg_count > 0) {
          chrome.browserAction.setBadgeText({text: msg_count + ""})
        }else{
          chrome.browserAction.setBadgeText({text: ""})
        }
      })
    }
  }
})

chrome.storage.onChanged.addListener((c, n) => {
  if (n === "sync") {
    username = c.username.newValue
  }
})

chrome.browserAction.onClicked.addListener(() => {
  chrome.tabs.create({
    url: "https://scratch.mit.edu/messages"
  })
})

Make browserAction link to /messages


'use strict';

module.exports = defineRules;

var competitivePhrases = [
    'best', 'compete', 'competition', 'competitive', 'cutting edge', 'fail', 'forefront',
    'superstar', 'top', 'win'
];

var expectationPhrases = [
    'hit the ground running',
    'juggle',
    'tight deadline', 'tight deadlines'
];

function defineRules (linter) {

    // Competitive environment
    linter.addRule(function (spec, result) {
        var competitionMentions = spec.containsAnyOfPhrases(competitivePhrases);
        if (competitionMentions.length > 0) {
            result.addNotice('The job sounds competitive and performance-based');
            result.addRealismFailPoints(competitionMentions.length / 2);
            result.addRecruiterFailPoints(competitionMentions.length / 2);
        }
    });

    // Unrealistic expectations
    linter.addRule(function (spec, result) {
        var expectationMentions = spec.containsAnyOfPhrases(expectationPhrases);
        if (expectationMentions.length > 0) {
            result.addNotice('The job sounds like it\'s expecting too much from a new starter');
            result.addRealismFailPoints(expectationMentions.length);
        }
    });

}

'use strict';

module.exports = defineRules;

var competitivePhrases = [
    'compete', 'competition', 'competitive', 'cutting edge', 'fail', 'forefront',
    'superstar', 'the best', 'top', 'win'
];

var expectationPhrases = [
    'hit the ground running',
    'juggle',
    'tight deadline', 'tight deadlines'
];

function defineRules (linter) {

    // Competitive environment
    linter.addRule(function (spec, result) {
        var competitionMentions = spec.containsAnyOfPhrases(competitivePhrases);
        if (competitionMentions.length > 0) {
            result.addNotice('The job sounds competitive and performance-based');
            result.addRealismFailPoints(competitionMentions.length / 2);
            result.addRecruiterFailPoints(competitionMentions.length / 2);
        }
    });

    // Unrealistic expectations
    linter.addRule(function (spec, result) {
        var expectationMentions = spec.containsAnyOfPhrases(expectationPhrases);
        if (expectationMentions.length > 0) {
            result.addNotice('The job sounds like it\'s expecting too much from a new starter');
            result.addRealismFailPoints(expectationMentions.length);
        }
    });

}

Change "best" to "the best"


const express = require('express');
const app = express();
const gpio = require('wiring-pi');
const socket = require('express-ws')(app);

// setup pi connection
gpio.wiringPiSetup();
gpio.pinMode(8, gpio.INPUT);

const tilt = () => {
	// testing whether it's digital or analog
	// return gpio.analogRead(8);
	return gpio.digitalRead(8);
}

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

// listen for websocket connections
app.ws('/', function(ws, req) {
	// event listener waiting for message via socket connection
	ws.on('message', (message) => {
		console.log('received: ${message}');
	});

	// event listener waiting for connection to close
	ws.on('end', () => {
		console.log('Connection ended...');
	});

	// send a reading from tilt sensor every 50 ms
	setInterval(()=>{
		let tilt_value = tilt();
		console.log(tilt_value)
		ws.send(tilt_value);
	}, 50);

});

// testing
setInterval(()=>{
	let tilt_value = tilt();
	console.log(tilt_value)
}, 500);

app.listen(3000, () => {
	console.info('Server started on port 3000');
})

const express = require('express');
const app = express();
const gpio = require('wiring-pi');
const socket = require('express-ws')(app);

// setup pi connection
gpio.wiringPiSetup();
gpio.pinMode(8, gpio.INPUT);
gpio.pinMode(9, gpio.INPUT);

const tilt = () => {
	// return gpio.analogRead(8);
	return gpio.digitalRead(8);
}

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

// listen for websocket connections
app.ws('/', function(ws, req) {
	// event listener waiting for message via socket connection
	ws.on('message', (message) => {
		console.log('received: ${message}');
	});

	// event listener waiting for connection to close
	ws.on('end', () => {
		console.log('Connection ended...');
	});

	// send a reading from tilt sensor every 50 ms
	setInterval(()=>{
		let tilt_value = tilt();
		console.log(tilt_value)
		ws.send(tilt_value);
	}, 50);

});

// testing
setInterval(()=>{
	let tilt_value = tilt();
//	console.log('tilt switch' + tilt_value);
	console.log('mercury digital switch' + gpio.digitalRead(9));
	console.log('mercury analog switch' + gpio.analogRead(9));
}, 500);

app.listen(3000, () => {
	console.info('Server started on port 3000');
})

Add test code for mercury switch


import { test, module } from 'qunit';
import ModelDouble from '../helpers/model-double';
import StoreDouble from '../helpers/store-double';
import Compiler from 'graphql-adapter/compiler';

module('unit:graphql-adapter/compiler');

test("takes an Model and responds with GraphQL query", function(assert) {
  let model = new ModelDouble('project', ['status']);
  let store = new StoreDouble({ 'project': model });
  let options = {
    'operationType': 'query',
    'operationName': 'projectsQuery',
    'rootFieldName': 'projects',
    'rootFieldQuery': {
      'status': 'active',
      'limit': 10
    }
  };

  assert.equal(Compiler.compile(model, store, options), 'query projectsQuery { projects(status: "active", limit: 10) { id  status } } ');
});

test("mutation", function(assert){
  let model = new ModelDouble('project', ['name', 'status']);
  let store = new StoreDouble({ 'project': model });
  let options = {
    'operationType': 'mutation',
    'operationName': 'projectCreate',
    'rootFieldName': 'projectCreate',
    'rootFieldQuery': {
      'name': 'Test Project',
      'status': 'active'
    }
  };

  assert.equal(Compiler.compile(model, store, options), 'mutation projectCreate { projectCreate(name: "Test Project", status: "active") { id  name  status } } ');
});

Add a basic test to show mutation can be done