/* global describe, it, expect */
import { Tab, Tabs, TabList, TabPanel } from '../main';
import TabComponent from '../components/Tab';
import TabListComponent from '../components/TabList';
import TabsComponent from '../components/Tabs';
import TabPanelComponent from '../components/TabPanel';

describe('<TabList />', () => {
  it('should correctly export all components', () => {
    expect(Tab).toEqual(TabComponent);
    expect(TabList).toEqual(TabListComponent);
    expect(Tabs).toEqual(TabsComponent);
    expect(TabPanel).toEqual(TabPanelComponent);
  });
});

/* global describe, it, expect */
import ReactTabs, { Tab, Tabs, TabList, TabPanel } from '../main';
import TabComponent from '../components/Tab';
import TabListComponent from '../components/TabList';
import TabsComponent from '../components/Tabs';
import TabPanelComponent from '../components/TabPanel';

describe('main.js', () => {
  it('should correctly export all component as named export', () => {
    expect(Tab).toEqual(TabComponent);
    expect(TabList).toEqual(TabListComponent);
    expect(Tabs).toEqual(TabsComponent);
    expect(TabPanel).toEqual(TabPanelComponent);
  });

  it('should correctly export all components as legacy es6 export', () => {
    expect(ReactTabs.Tab).toEqual(TabComponent);
    expect(ReactTabs.TabList).toEqual(TabListComponent);
    expect(ReactTabs.Tabs).toEqual(TabsComponent);
    expect(ReactTabs.TabPanel).toEqual(TabPanelComponent);
  });
});

Add tests for main export


/*
  This is the client side JavaScript.
  This is a VERY basic client. It is little more than the 'hello world' of chatrooms!

  Good improvements would be:
   to prevent the user from sending empty messages
   to force the user to enter a username
*/

var socket = io.connect();
socket.on('chatmessage', function (data) {
  div = document.getElementById('chatHistory');
  div.innerHTML = div.innerHTML + '<br />' + data.user + ': ' + data.message;
});

function sendChatText(){
	socket.emit('chatmessage', { user: document.getElementById("userName").value,
							message: document.getElementById("inputLine").value }); //Send to server.
	document.getElementById("inputLine").value=""; //Clear line ready for next message input.
	document.getElementById("inputLine").focus(); //Set input focus ready for next message.
};

/*
  This is the client side JavaScript.
  This is a VERY basic client. It is little more than the 'hello world' of chatrooms!

  Good improvements would be:
   to prevent the user from sending empty messages
   to force the user to enter a username
*/

var socket = io.connect();
socket.on('chatmessage', function (data) {
  div = document.getElementById('chatHistory');
  div.innerHTML = div.innerHTML + '<br />' + data.user + ': ' + data.message;
  window.scrollTo(0,document.body.scrollHeight);
});

function sendChatText(){
	socket.emit('chatmessage', { user: document.getElementById("userName").value,
							message: document.getElementById("inputLine").value }); //Send to server.
	document.getElementById("inputLine").value=""; //Clear line ready for next message input.
	document.getElementById("inputLine").focus(); //Set input focus ready for next message.
};

Make window scroll to bottom after each message received


import { moduleForModel, test } from 'ember-qunit';

moduleForModel('event', 'Unit | Serializer | event', {
  needs: [
    'serializer:event',
    'serializer:user',
    'serializer:event-topic',
    'model:event-type',
    'model:event-topic',
    'model:event-sub-topic',
    'model:session',
    'model:sponsor',
    'model:microlocation',
    'model:track',
    'model:ticket',
    'model:social-link',
    'model:attendee',
    'model:speaker',
    'model:speakers-call',
    'model:email-notification',
    'model:custom-form',
    'model:tax',
    'model:event-copyright',
    'model:session-type',
    'model:user',
    'model:order-statistics-event',
    'model:event-invoice',
    'model:discount-code',
    'model:access-code',
    'model:order',
    'transform:moment'
  ]
});

test('it serializes records', function(assert) {
  let record = this.subject();

  let serializedRecord = record.serialize();

  assert.ok(serializedRecord);
});

import { moduleForModel, test } from 'ember-qunit';

moduleForModel('event', 'Unit | Serializer | event', {
  needs: [
    'serializer:event',
    'serializer:user',
    'serializer:event-topic',
    'model:event-type',
    'model:event-topic',
    'model:event-sub-topic',
    'model:session',
    'model:sponsor',
    'model:microlocation',
    'model:track',
    'model:ticket',
    'model:social-link',
    'model:attendee',
    'model:speaker',
    'model:speakers-call',
    'model:email-notification',
    'model:custom-form',
    'model:tax',
    'model:event-copyright',
    'model:session-type',
    'model:user',
    'model:order-statistics-event',
    'model:event-statistics-general',
    'model:event-invoice',
    'model:discount-code',
    'model:access-code',
    'model:order',
    'transform:moment'
  ]
});

test('it serializes records', function(assert) {
  let record = this.subject();

  let serializedRecord = record.serialize();

  assert.ok(serializedRecord);
});

Add event-statistics-general model to event serializer test


(function($) {

var plugin = "Echo.StreamServer.Controls.Stream.Item.Plugins.Reply";

Echo.Tests.module(plugin, {
	"meta": {
		"className": plugin
	}
});

Echo.Tests.pluginRenderersTest(plugin, {
	"query": "childrenof:http://example.com/js-sdk/",
	"liveUpdates": {
		"enabled": false
	}
});

})(Echo.jQuery);

(function($) {

var plugin = "Echo.StreamServer.Controls.Stream.Item.Plugins.Reply";

Echo.Tests.module(plugin, {
	"meta": {
		"className": plugin,
		"functions": [
			"destroy"
		]
	}
});

Echo.Tests.pluginRenderersTest(plugin, {
	"query": "childrenof:http://example.com/js-sdk/",
	"liveUpdates": {
		"enabled": false
	}
});

})(Echo.jQuery);

Add back info about covered methods for Reply plugin


/* jshint bitwise: true,
          curly: true,
          eqeqeq: true,
          esversion: 6,
          forin: true,
          freeze: true,
          latedef: nofunc,
          noarg: true,
          nocomma: true,
          node: true,
          nonbsp: true,
          nonew: true,
          plusplus: true,
          singleGroups: true,
          strict: true,
          undef: true,
          unused: true
*/

'use strict';

const gulp = require('gulp');

const BUILD_OUTPUT_DIR = 'build';
const NODE_MODULES_BIN_DIR = 'node_modules/.bin';

function exec(command, callback) {
  require('child_process').exec(command, (err) => {
    if (err) {
      return callback(err);
    }
    callback();
  });
}

function execJsDoc(configPath, callback) {
  exec(`${NODE_MODULES_BIN_DIR}/jsdoc -c ${configPath}`, callback);
}

gulp.task('clean', () => {
  const del = require('del');
  return del([BUILD_OUTPUT_DIR]);
});

gulp.task('docs:client', (callback) => {
  execJsDoc('.jsdoc-client-conf.json', callback);
});

gulp.task('docs:server', (callback) => {
  execJsDoc('.jsdoc-server-conf.json', callback);
});

gulp.task('docs', ['docs:client', 'docs:server']);

/* jshint bitwise: true,
          curly: true,
          eqeqeq: true,
          esversion: 6,
          forin: true,
          freeze: true,
          latedef: nofunc,
          noarg: true,
          nocomma: true,
          node: true,
          nonbsp: true,
          nonew: true,
          plusplus: true,
          singleGroups: true,
          strict: true,
          undef: true,
          unused: true
*/

'use strict';

const gulp = require('gulp');

const BUILD_OUTPUT_DIR = 'build';
const NODE_MODULES_BIN_DIR = 'node_modules/.bin';

function exec(command, callback) {
  require('child_process').exec(command, (err) => {
    if (err) {
      return callback(err);
    }
    callback();
  });
}

function execJsDoc(configPath, callback) {
  exec(`${NODE_MODULES_BIN_DIR}/jsdoc -c ${configPath}`, callback);
}

gulp.task('clean', () => {
  const del = require('del');
  return del([BUILD_OUTPUT_DIR]);
});

gulp.task('docs:client', (done) => {
  execJsDoc('.jsdoc-client-conf.json', done);
});

gulp.task('docs:server', (done) => {
  execJsDoc('.jsdoc-server-conf.json', done);
});

gulp.task('docs', ['docs:client', 'docs:server']);

Rename task callbacks to match Gulp standards


var gulp = require('gulp'),
    ts = require('gulp-typescript'),
    sourcemaps = require('gulp-sourcemaps'),
    del = require('del'),
    shell = require('gulp-shell');

gulp.task('ts', ['clean'], function () {
    var tsProject = ts.createProject({
        target: 'ES5',
        declarationFiles: true,
        noExternalResolve: false,
        removeComments: true,
        module: 'commonjs'
    });
    var tsResult = gulp.src('src/*.ts')
        .pipe(sourcemaps.init())
        .pipe(ts(tsProject));
        tsResult.dts.pipe(gulp.dest('./dist'));

    tsResult.js
        .pipe(sourcemaps.write('.'))
        .pipe(gulp.dest('./dist'));
});

gulp.task('clean', function() {
    del(['dist'], function (err, deletedFiles) {
        console.log('Files deleted:', deletedFiles.join(', '));
    });
});

gulp.task('test', ['clean', 'ts'], shell.task([
    'zuul --local 8080 -- ./test/*-Test.js'
]));

gulp.task('phantom', ['clean', 'ts'], shell.task([
    'zuul --phantom -- ./test/*-Test.js'
]));

var gulp = require('gulp'),
    ts = require('gulp-typescript'),
    sourcemaps = require('gulp-sourcemaps'),
    del = require('del'),
    shell = require('gulp-shell');

gulp.task('ts', ['clean'], function () {
    var tsProject = ts.createProject({
        target: 'ES5',
        declarationFiles: true,
        noExternalResolve: false,
        removeComments: true,
        //typescript: require('typescript'),
        module: 'commonjs'
    });
    var tsResult = gulp.src('src/*.ts')
        .pipe(sourcemaps.init())
        .pipe(ts(tsProject));
        tsResult.dts.pipe(gulp.dest('./dist'));

    tsResult.js
        .pipe(sourcemaps.write('.'))
        .pipe(gulp.dest('./dist'));
});

gulp.task('clean', function() {
    del(['dist'], function (err, deletedFiles) {
        console.log('Files deleted:', deletedFiles.join(', '));
    });
});

gulp.task('test', ['clean', 'ts'], shell.task([
    'zuul --local 8080 -- ./test/*-Test.js'
]));

gulp.task('phantom', ['clean', 'ts'], shell.task([
    'zuul --phantom -- ./test/*-Test.js'
]));

Add ts 1.5 commented declaration


var gulp = require('gulp');
var del = require('del');
var ts = require('gulp-typescript');
var mocha = require('gulp-mocha');

var tsProject = ts.createProject('tsconfig.json');

gulp.task('clean:build', function () {
  return del([
    tsProject.config.compilerOptions.outDir + '/*',
	tsProject.config.compilerOptions.outDir + '/.*'
  ]);
});

gulp.task('compile', function () {
	var tsResult = tsProject.src()
		.pipe(ts(tsProject));
	return tsResult.js.pipe(gulp.dest(tsProject.config.compilerOptions.outDir));
});

gulp.task('test', function () {
    return gulp.src(tsProject.config.compilerOptions.outDir + '/**/*.spec.js', {read: false})
        .pipe(mocha({reporter: 'nyan'}));
});

gulp.task('build:incremental', ['compile'], function() {
	gulp.start('test');
});

gulp.task('build:clean', ['clean:build'], function() {
	gulp.start('build:incremental');
});

gulp.task('watch', function() {
	gulp.watch(tsProject.config.files, ['build:incremental']);
});

gulp.task('default', ['build:clean'], function() {
	gulp.start('watch');
});

var gulp = require('gulp');
var del = require('del');
var ts = require('gulp-typescript');
var mocha = require('gulp-mocha');
var connect = require('gulp-connect');

var tsProject = ts.createProject('tsconfig.json');

gulp.task('clean:build', function () {
  return del([
    tsProject.config.compilerOptions.outDir + '/*',
	tsProject.config.compilerOptions.outDir + '/.*'
  ]);
});

gulp.task('compile', function () {
	var tsResult = tsProject.src()
		.pipe(ts(tsProject));
	return tsResult.js.pipe(gulp.dest(tsProject.config.compilerOptions.outDir));
});

gulp.task('connect', function() {
	connect.server({
		root: 'docs/sample',
		port: 8081
	});
});

gulp.task('test', function () {
    return gulp.src(tsProject.config.compilerOptions.outDir + '/**/*.spec.js', {read: false})
        .pipe(mocha({reporter: 'nyan'}));
});

gulp.task('build:incremental', ['compile'], function() {
	gulp.start('test');
});

gulp.task('build:clean', ['clean:build'], function() {
	gulp.start('build:incremental');
});

gulp.task('watch', ['connect'], function() {
	gulp.watch(tsProject.config.files, ['build:incremental']);
});

gulp.task('default', ['build:clean'], function() {
	gulp.start('watch');
});

Add connect task fo dev web server


var gulp = require('gulp');
var tsc = require('gulp-tsc');
var tape = require('gulp-tape');
var tapSpec = require('tap-spec');
var del = require('del');

gulp.task("test:clean", function(done) {
  del(['build-test/**']).then(function(paths) {
    console.log("=====\nDeleted the following files:\n" + paths.join('\n')+ "\n=====");
    done();
  });
});

gulp.task("test:build", function (done) {
  gulp.src(['test/**/*.ts'])
    .pipe(tsc())
    .pipe(gulp.dest('build-test/'))
    .on('end', done);
});

gulp.task("test:run", function (done) {
  gulp.src('build-test/test/**/*.test.js')
    .pipe(tape({
      reporter: tapSpec()
    }))
    .on('end', done);;
});

gulp.task("test", ["test:build"], function (done) {
  gulp.src('build-test/test/**/*.test.js')
    .pipe(tape({
      reporter: tapSpec()
    }));
});

var gulp = require('gulp');
var tsc = require('gulp-tsc');
var tape = require('gulp-tape');
var tapSpec = require('tap-spec');
var del = require('del');
var runSequence = require('run-sequence');

gulp.task("test:clean", function(done) {
  del(['build-test/**']).then(function(paths) {
    console.log("=====\nDeleted the following files:\n" + paths.join('\n')+ "\n=====");
    done();
  });
});

gulp.task("test:build", function (done) {
  gulp.src(['test/**/*.ts'])
    .pipe(tsc())
    .pipe(gulp.dest('build-test/'))
    .on('end', done);
});

gulp.task("test:run", function (done) {
  gulp.src('build-test/test/**/*.test.js')
    .pipe(tape({
      reporter: tapSpec()
    }))
    .on('end', done);;
});

gulp.task("test", function (done) {
  runSequence('test:clean', 'test:build', 'test:run', done);
});

Make test task run the test parts in sequence


'use strict';

var EventEmitter = require('events').EventEmitter;
var mixin = require('merge-descriptors');

function Command() {
  this.actions = [];

  mixin(this, EventEmitter.prototype, false);
}

Command.prototype._findAction = function (text) {
  var action;

  for(var i = 0; i < this.actions.length; i++) {
    action = this.actions[i];
    if(action.pattern.test(text)) {
      return action;
    }
  }
};

Command.prototype.action = function (pattern, callback) {
  this.actions.push({pattern: pattern, callback: callback});
};

Command.prototype.execute = function (data) {
  var text = data.text;
  var action = this.findAction(text);

  if(action) {
    var matches = action.pattern.exec(text);

    try {
      this.emit('success', action.callback(data, matches));
    } catch(e) {
      this.emit('error', e);
    }
  } else {
    this.emit('error', 'No matching action found to handle ' + text);
  }
};

exports.Command = Command;

'use strict';

var EventEmitter = require('events').EventEmitter;
var mixin = require('merge-descriptors');

function Command() {
  this.actions = [];

  mixin(this, EventEmitter.prototype, false);
}

Command.prototype._findAction = function (text) {
  var action;

  for(var i = 0; i < this.actions.length; i++) {
    action = this.actions[i];

    if(action.pattern.test(text)) {
      return action;
    }
  }
};

Command.prototype.action = function (pattern, callback) {
  this.actions.push({pattern: new RegExp(pattern), callback: callback});
};

Command.prototype.execute = function (data) {
  var text = data.text;
  var action = this._findAction(text);

  if(action) {
    var matches = action.pattern.exec(text);

    try {
      this.emit('success', action.callback(data, matches));
    } catch(e) {
      this.emit('error', e);
    }
  } else {
    this.emit('error', 'No matching action found to handle ' + text);
  }
};

exports.Command = Command;

Make patterns into regular expressions.


var CompositeDisposable, Synesthesia;

CompositeDisposable = require('atom').CompositeDisposable;
var T = require('timbre');

module.exports = Synesthesia = {
  activate: function() {
    this.subscriptions = new CompositeDisposable;
    return this.subscriptions.add(atom.commands.add('atom-workspace', {
      'synesthesia:toggle': (function(_this) {
        return function() {
          return _this.toggle();
        };
      })(this)
    }));
  },
  toggle: function() {
    console.log('Synesthesia was toggled!');
    T("sin").play();
  }
};

var CompositeDisposable, Synesthesia, T, playing, sound;

CompositeDisposable = require('atom').CompositeDisposable;
T = require('timbre');
sound = T('sin');
playing = false;

module.exports = Synesthesia = {
  activate: function() {
    this.subscriptions = new CompositeDisposable;
    return this.subscriptions.add(atom.commands.add('atom-workspace', {
      'synesthesia:toggle': (function(_this) {
        return function() {
          return _this.toggle();
        };
      })(this)
    }));
  },
  toggle: function() {
    console.log('Synesthesia was toggled!');

    if (playing) {
      console.log('pausing...');
      sound.pause();
      playing = false;
    } else {
      console.log('resuming...');
      sound.play();
      playing = true;
    }
  }
};

Add ability to toggle sound


(function( $ ) {
	function setHeaderHeight() {
		$( '#screen-fill' ).css( 'height', $( window ).height() - 50 );
	}

	$( window ).load( setHeaderHeight );
	$( window ).resize( setHeaderHeight );
} )( jQuery );

(function( $ ) {
	function setHeaderHeight() {
		$( '#screen-fill' ).css( 'height', $( window ).height() - 50 );
	}

	$( document ).ready( setHeaderHeight );
	$( window ).resize( setHeaderHeight );
} )( jQuery );

Change event from window load to dom ready.


// @flow
import RenderSuccess from './index.render'
import {connect} from 'react-redux'
import {sawPaperKey} from '../../../actions/signup'
import {navigateUp} from '../../../actions/route-tree'

// $FlowIssue
export default connect(
  state => ({
    paperkey: state.signup.paperkey,
    waiting: state.signup.waiting,
  }),
  dispatch => ({
    onFinish: () => { dispatch(sawPaperKey()) },
    onBack: () => { dispatch(navigateUp()) },
  })
)(RenderSuccess)

// @flow
import RenderSuccess from './index.render'
import {connect} from 'react-redux'
import {sawPaperKey} from '../../../actions/signup'
import {navigateUp} from '../../../actions/route-tree'

type OwnProps = any

export default connect(
  (state: any, {routeProps}: OwnProps) => ({
    paperkey: state.signup.paperkey,
    waiting: state.signup.waiting,
    ...routeProps,
  }),
  (dispatch, {routeProps}: OwnProps) => ({
    onFinish: routeProps.onFinish ? routeProps.onFinish : () => { dispatch(sawPaperKey()) },
    onBack: routeProps.onBack ? routeProps.onBack : () => { dispatch(navigateUp()) },
  })
)(RenderSuccess)

Fix prop routing for login path through success


// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
// GO AFTER THE REQUIRES BELOW.
//
//= require_tree .
//= require chosen.jquery

// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
// GO AFTER THE REQUIRES BELOW.
//
//= require jquery
//= require_tree .
//= require chosen.jquery

Add require jquery that got lost in the merge


'use strict';

/*jslint
    browser: true
*/

var divs = document.getElementsByTagName('div'),
    i;

function fancify(div) {
    var ths = div.getElementsByTagName('th'),
        firstCellWidth,
        i;
    for (i = ths.length - 1; i >= 0; i -= 1) {
        if (ths[i].offsetWidth) {
            firstCellWidth = ths[i].offsetWidth + 'px';
            break;
        }
    }
    for (i = ths.length - 1; i >= 0; i -= 1) {
        ths[i].style.width = firstCellWidth;
        ths[i].style.marginLeft = '-' + firstCellWidth;
    }
    div.style.marginLeft = firstCellWidth;
    div.className += ' fancy';
}

for (i = divs.length - 1; i >= 0; i -= 1) {
    if (divs[i].className === 'timetable-wrapper') {
        fancify(divs[i]);
    }
}

'use strict';

/*jslint
    browser: true
*/

(function() {
    var divs = document.getElementsByTagName('div'),
        i,
        selects = document.getElementsByTagName('select'),
        options;

    function fancify(div) {
        var ths = div.getElementsByTagName('th'),
            firstCellWidth,
            i;
        for (i = ths.length - 1; i >= 0; i -= 1) {
            if (ths[i].offsetWidth) {
                firstCellWidth = ths[i].offsetWidth + 'px';
                break;
            }
        }
        for (i = ths.length - 1; i >= 0; i -= 1) {
            ths[i].style.width = firstCellWidth;
            ths[i].style.marginLeft = '-' + firstCellWidth;
        }
        div.style.marginLeft = firstCellWidth;
        div.className += ' fancy';
    }

    for (i = divs.length - 1; i >= 0; i -= 1) {
        if (divs[i].className === 'timetable-wrapper') {
            fancify(divs[i]);
        }
    }

    if (selects.length) {
        options = selects[0].getElementsByTagName('option');
        for (i = options.length - 1; i >= 0; i -= 1) {
            if (options[i].defaultSelected) {
                if (!options[i].selected) {
                    selects[0].value = options[i].value;
                }
                break;
            }
        }
    }
}());

Use javascript to prevent confusion when using the back button after changing date


var canvas = new fabric.Canvas('draughts-canvas');
canvas.setBackgroundColor("#ffffff");
var mousePos;
var board;
var Color = net.brehaut.Color; //TODO move to bower
var hoverAnimationTime = 100;
var colorAnimationTime = 300;
var manAnimationTime = 700;
var socketURL = 'http://localhost:3000';

var websocket = new Websocket(socketURL);

// function draw() {
//   board.draw();
//   // window.requestAnimationFrame(draw);
// }

// function run() {
//   board = new Board();
//   // draw();
// }

canvas.on('mouse:over', function(e) {
  if (e.target.obj.onMouseOver) {
    e.target.obj.onMouseOver();
    canvas.renderAll();
  }
});

canvas.on('mouse:out', function(e) {
  if (e.target.obj.onMouseOut) {
    e.target.obj.onMouseOut();
    canvas.renderAll();
  }
});

canvas.on('mouse:down', function(e) {
  if (e.target.obj.onMouseDown) {
    e.target.obj.onMouseDown();
    canvas.renderAll();
  }
});

canvas.on('mouse:up', function(e) {
  if (e.target.obj.select) {
    e.target.obj.select();
    canvas.renderAll();
  }
});
// canvas.onMouseOut = function() {
//   console.log('mouseOut');
// };

// run();

var canvas = new fabric.Canvas('draughts-canvas');
canvas.setBackgroundColor("#ffffff");
var board;
var Color = net.brehaut.Color;
var hoverAnimationTime = 100;
var colorAnimationTime = 300;
var manAnimationTime = 700;

var socketURL = document.location.origin;
var websocket = new Websocket(socketURL);

// function draw() {
//   board.draw();
//   // window.requestAnimationFrame(draw);
// }

// function run() {
//   board = new Board();
//   // draw();
// }

canvas.on('mouse:over', function(e) {
  if (e.target.obj.onMouseOver) {
    e.target.obj.onMouseOver();
    canvas.renderAll();
  }
});

canvas.on('mouse:out', function(e) {
  if (e.target.obj.onMouseOut) {
    e.target.obj.onMouseOut();
    canvas.renderAll();
  }
});

canvas.on('mouse:down', function(e) {
  if (e.target.obj.onMouseDown) {
    e.target.obj.onMouseDown();
    canvas.renderAll();
  }
});

canvas.on('mouse:up', function(e) {
  if (e.target.obj.select) {
    e.target.obj.select();
    canvas.renderAll();
  }
});
// canvas.onMouseOut = function() {
//   console.log('mouseOut');
// };

// run();

Change WebSocket URL to server's domain address


var JSONDumper = function() {
	this.onBrowserLog = function(browser, log, type) {
		if( type != "dump" ) {
			return;
		}

		var objectMerge = require( 'object-merge' );
		var fs = require( 'fs' );

		var logObj = JSON.parse(log.substring(1, log.length-1));
		var fileObj;
		var data;
		for( var file in logObj ) {
			data = fs.readFileSync("test/er/" + file + ".json", { "flag": "a+"});
			fileObj = JSON.parse(data.toString());
			fileObj = objectMerge( fileObj, logObj[file] );
			fs.writeFileSync("test/er/" + file + ".json", JSON.stringify(fileObj, null, " "));
		}
	};

};

module.exports = {
  'reporter:json-dumper': ['type', JSONDumper]
};

var JSONDumper = function() {
	this.onBrowserLog = function(browser, log, type) {
		if( type != "dump" ) {
			return;
		}

		var objectMerge = require( 'object-merge' );
		var fs = require( 'fs' );

		var logObj = JSON.parse(log.substring(1, log.length-1));
		var fileObj;
		var data;
		for( var file in logObj ) {
			data = fs.readFileSync("test/er/" + file + ".json", { "flag": "a+"});
			fileObj = data.length != 0 ? JSON.parse(data.toString()) : {};
			fileObj = objectMerge( fileObj, logObj[file] );
			fs.writeFileSync("test/er/" + file + ".json", JSON.stringify(fileObj, null, " "));
		}
	};

};

module.exports = {
  'reporter:json-dumper': ['type', JSONDumper]
};

Handle the empty er folder and blank ER case properly.


var express = require('express');
var router = express.Router();
var cors = require('./cors');
var HttpError = require('./errors').HttpError;
var db = require('../libs/db');

router.use(cors);

router.get('/', function(req, res, next) {
    var page = req.query.page || 0;

    var collection = db.get().collection('workings');
    var q = {};
    var opt = {
            company_id: 1,
            company_name: 1,
            week_work_time: 1,
            job_title: 1,
            created_at: 1,
        };
    collection.find(q, opt).sort({created_at: -1}).skip(25 * page).limit(25).toArray().then(function(results) {
        res.send(results);
    }).catch(function(err) {
        next(new HttpError("Internal Server Error", 500));
    });
});

module.exports = router;

var express = require('express');
var router = express.Router();
var cors = require('./cors');
var HttpError = require('./errors').HttpError;
var db = require('../libs/db');

router.use(cors);

router.get('/', function(req, res, next) {
    var page = req.query.page || 0;

    var collection = db.get().collection('workings');
    var q = {};
    var opt = {
            company: 1,
            week_work_time: 1,
            job_title: 1,
            created_at: 1,
        };
    collection.find(q, opt).sort({created_at: -1}).skip(25 * page).limit(25).toArray().then(function(results) {
        res.send(results);
    }).catch(function(err) {
        next(new HttpError("Internal Server Error", 500));
    });
});

module.exports = router;

Change to include company field


import React from "react";

const Template = ({ children }) => (
  <html lang="en">

    <head>
      <meta charSet="utf-8" />
      <meta httpEquiv="X-UA-Compatible" content="IE=edge,chrome=1" />
      <meta name="viewport" content="width=device-width, initial-scale=1" />
      <meta name="author" content="Sylvain Boulade" />
      <link href="https://fonts.googleapis.com/css?family=Raleway" rel="stylesheet" />
      <link rel="stylesheet" href="main.css" />
      <title>Sylvain {"'"}hihuz{"'"} Boulade</title>
      <link rel="apple-touch-icon" sizes="180x180" href="apple-touch-icon.png" />
      <link rel="icon" type="image/png" href="favicon-32x32.png" sizes="32x32" />
      <link rel="icon" type="image/png" href="favicon-16x16.png" sizes="16x16" />
      <link rel="manifest" href="manifest.json" />
      <meta name="theme-color" content="#333e4b" />
    </head>

    <body>
      {children}
      <script src="install.js" />
    </body>

  </html>
);

export default Template;

import React from "react";

const Template = ({ children }) => (
  <html lang="en">

    <head>
      <meta charSet="utf-8" />
      <meta httpEquiv="X-UA-Compatible" content="IE=edge,chrome=1" />
      <meta name="viewport" content="width=device-width, initial-scale=1" />
      <meta name="author" content="Sylvain Boulade" />
      <link href="https://fonts.googleapis.com/css?family=Raleway" rel="stylesheet" />
      <link rel="stylesheet" href="main.css" />
      <title>Sylvain {"'"}hihuz{"'"} Boulade</title>
      <link rel="apple-touch-icon" sizes="180x180" href="apple-touch-icon.png" />
      <link rel="icon" type="image/png" href="favicon-32x32.png" sizes="32x32" />
      <link rel="icon" type="image/png" href="favicon-16x16.png" sizes="16x16" />
      <link rel="manifest" href="manifest.json" />
      <meta name="theme-color" content="#333e4b" />
    </head>

    <body>
      {children}
      <script src="install.js" async />
    </body>

  </html>
);

export default Template;

Add async attribute back to the install script


Console = {}

Console.puts = function(str, no_newline) {
    var text = (str + (no_newline ? "" : "\n")).escapeHTML();
    span = document.createElement("span");
    span.innerHTML = text.replace(/\n/g,"<br>").replace(/ /g," ");
    $('bs-console').insert(span);
}

Console.p = function (/*ARGS*/){
    Console.puts("p> "+$A(arguments).map(Object.inspect).join(" "));
}

Console = {}

Console.puts = function(str, no_newline) {
    var console;
    var text
    console = $('bs-console');
    if (console) {
	text = (str + (no_newline ? "" : "\n")).escapeHTML();
	span = document.createElement("span");
	span.innerHTML = text.replace(/\n/g,"<br>").replace(/ /g," ");
	console.insert(span);
    }
}

Console.p = function (/*ARGS*/){
    Console.puts("p> "+$A(arguments).map(Object.inspect).join(" "));
}

Handle the case that bs-console doesn't exist.


define('soundMatrixConstants', function () {
    'use strict';

    var matrix = [
        [false, false, false, false, false, false, false, false],
        [false, false, false, false, false, false, false, false],
        [false, false, false, false, false, false, false, false],
        [false, false, false, false, false, false, false, false],
        [false, false, false, false, false, false, false, false],
        [false, false, false, false, false, false, false, false]
    ];

    return {
        getMatrix: getMatrix
    }

    function getMatrix() {
        return matrix;
    }
});

define('soundMatrixConstants', function () {
    'use strict';

    var matrix = [
        { id: 'basskick', value: [false, false, false, false, false, false, false, false] },
        { id: 'cowbell', value: [false, false, false, false, false, false, false, false] },
        { id: 'hihat', value: [false, false, false, false, false, false, false, false] },
        { id: 'snare', value: [false, false, false, false, false, false, false, false] },
        { id: 'tom1', value: [false, false, false, false, false, false, false, false] },
        { id: 'tom2', value: [false, false, false, false, false, false, false, false] }
    ];

    return {
        getMatrix: getMatrix
    }

    function getMatrix() {
        return matrix;
    }
});

Add sound id to matrix


JARS.internal('ConfigTransforms/CheckCircularDeps', function() {
    'use strict';

    /**
     * @memberof JARS.internals.ConfigTransforms
     *
     * @param {boolean} value
     *
     * @return {boolean}
     */
    function CheckCircularDeps(checkCircularDeps) {
        return checkCircularDeps;
    }

    return CheckCircularDeps;
});

JARS.internal('ConfigTransforms/CheckCircularDeps', function() {
    'use strict';

    /**
     * @memberof JARS.internals.ConfigTransforms
     *
     * @param {boolean} value
     *
     * @return {boolean}
     */
    function CheckCircularDeps(checkCircularDeps) {
        return !!checkCircularDeps;
    }

    return CheckCircularDeps;
});

Make sure that the return value is a boolean


import Ember from 'ember';

import OsfAgnosticAuthControllerMixin from 'ember-osf/mixins/osf-agnostic-auth-controller';

import {
    getAuthUrl
} from 'ember-osf/utils/auth';

export default Ember.Controller.extend(OsfAgnosticAuthControllerMixin,{
    toast: Ember.inject.service(),
    authUrl: getAuthUrl(),
    actions: {
        loginSuccess() {
           // this.transitionToRoute('researcher.grant');
        },
        loginFail(/* err */) {
            this.get('toast').error('Login failed');
        },
        transitionToHome(){
            debugger;
            this.transitionToRoute('dashboards.dashboard', 'institution', {
                queryParams: {all : 'ucsd'}
            });
        }
    }
});

import Ember from 'ember';

import OsfAgnosticAuthControllerMixin from 'ember-osf/mixins/osf-agnostic-auth-controller';

import {
    getAuthUrl
} from 'ember-osf/utils/auth';

export default Ember.Controller.extend(OsfAgnosticAuthControllerMixin,{
    toast: Ember.inject.service(),
    authUrl: getAuthUrl(),
    actions: {
        loginSuccess() {
           // this.transitionToRoute('researcher.grant');
        },
        loginFail(/* err */) {
            this.get('toast').error('Login failed');
        },
        transitionToHome(){
            this.transitionToRoute('dashboards.dashboard', 'institution');
        }
    }
});

Fix app title link not working with ‘source’ query paremeter


({
    /**
     * Verify the correct AppCache events are received and are in the right order, without an error event.  This case
     * covers when we have not seen the page before and must download resources.
     */
    testAppCacheEvents: {
        // AppCache not supported on IE < 10
        browsers:["-IE7","-IE8","-IE9"],
        test: function(component){
            var appCacheEvents = $A.test.getAppCacheEvents();
            var lastEvent = appCacheEvents.length - 1;

            // Error event is always the last event in the sequence
            $A.test.assertNotEquals("error", appCacheEvents[lastEvent], "AppCache returned with an error.");

            // Verify we received the events in the right order
            $A.test.assertEquals("checking", appCacheEvents[0], "AppCache should begin with checking event.");
            $A.test.assertEquals("downloading", appCacheEvents[1], "AppCache did not start downloading resources.");

            // A progress event is fired for each file that is successfully downloaded. Only check that at least one
            // file has been downloaded then check that AppCache completed.
            $A.test.assertEquals("progress", appCacheEvents[2], "No files successfully downloaded.");
            $A.test.assertEquals("cached", appCacheEvents[lastEvent], "Cached event to signal all files downloaded never fired");
        }
    }
})

({
    /**
     * Verify the correct AppCache events are received and are in the right order, without an error event.  This case
     * covers when we have not seen the page before and must download resources.
     */
    testAppCacheEvents: {
        // AppCache not supported on IE < 10. Firefox displays a popup asking permission to use AppCache.
        browsers:["-FIREFOX","-IE7","-IE8","-IE9"],
        test: function(component){
            var appCacheEvents = $A.test.getAppCacheEvents();
            var lastEvent = appCacheEvents.length - 1;

            // Error event is always the last event in the sequence
            $A.test.assertNotEquals("error", appCacheEvents[lastEvent], "AppCache returned with an error.");

            // Verify we received the events in the right order
            $A.test.assertEquals("checking", appCacheEvents[0], "AppCache should begin with checking event.");
            $A.test.assertEquals("downloading", appCacheEvents[1], "AppCache did not start downloading resources.");

            // A progress event is fired for each file that is successfully downloaded. Only check that at least one
            // file has been downloaded then check that AppCache completed.
            $A.test.assertEquals("progress", appCacheEvents[2], "No files successfully downloaded.");
            $A.test.assertEquals("cached", appCacheEvents[lastEvent], "Cached event to signal all files downloaded never fired");
        }
    }
})

Exclude AppCache js test on Firefox


var Graphite = require('graphite');
var Measured = require('measured');

var reportInterval = 5000;
var graphiteHost = process.env.GRAPHITE_HOST || null;
var graphitePort = process.env.GRAPHITE_PORT || 2003;
var envName = process.env.NODE_ENV || "unknown";

var timer = null;
var graphite = null;
var data = Measured.createCollection('origami.polyfill.' + envName);

if (graphiteHost) {
	graphite = Graphite.createClient('plaintext://'+graphiteHost+':'+graphitePort);
	timer = setInterval(function() {
		graphite.write(data.toJSON(), function(err) {
			if (err) {

				// Ignore timeouts
				if (err.code === 'ETIMEDOUT') return;

				console.error(err, err.stack);
				console.warn('Disabling graphite reporting due to error');
				clearTimeout(timer);
			}
		});
	}, reportInterval);
	timer.unref();
}

module.exports = data;

var Graphite = require('graphite');
var Measured = require('measured');

var reportInterval = 5000;
var graphiteHost = process.env.GRAPHITE_HOST || null;
var graphitePort = process.env.GRAPHITE_PORT || 2003;
var envName = process.env.NODE_ENV || "unknown";
var processIdentifier = process.env.DYNO || "unknown-process";

var timer = null;
var graphite = null;
var data = Measured.createCollection('origami.polyfill.' + envName + '.' + processIdentifier);

if (graphiteHost) {
	graphite = Graphite.createClient('plaintext://'+graphiteHost+':'+graphitePort);
	timer = setInterval(function() {
		graphite.write(data.toJSON(), function(err) {
			if (err) {

				// Ignore timeouts
				if (err.code === 'ETIMEDOUT') return;

				console.error(err, err.stack);
				console.warn('Disabling graphite reporting due to error');
				clearTimeout(timer);
			}
		});
	}, reportInterval);
	timer.unref();
}

module.exports = data;

Include the dyno identifier, if available, in the metric key


/* eslint-disable no-unused-vars */
class Service {
  constructor (options) {
    this.options = options || {};
  }

  find (params) {
    console.log('params ==>', params)
    const { availableVideos } = params;
    let result = {
      message: 'OK',
      data: {
        availableVideos
      }
    };
    return Promise.resolve(result);
  }

  get (id, params) {
    return Promise.resolve({
      id, text: `A new message with ID: ${id}!`
    });
  }

  create (data, params) {
    // if (Array.isArray(data)) {
    //   return Promise.all(data.map(current => this.create(current)));
    // }

    console.log('watch request', data, params)
    // params.producer.send(req.profiler.sqsProducer, function(err) {
    //   if (err) console.log(err);
    // });

    return Promise.resolve(data);
  }

  update (id, data, params) {
    return Promise.resolve(data);
  }

  patch (id, data, params) {
    return Promise.resolve(data);
  }

  remove (id, params) {
    return Promise.resolve({ id });
  }
}

module.exports = function (options) {
  return new Service(options);
};

module.exports.Service = Service;

const errors = require('feathers-errors');
const uuidv4 = require('uuid/v4');

/* eslint-disable no-unused-vars */
class Service {
  constructor (options) {
    this.options = options || {};
  }

  find (params) {
    const { availableVideos } = params;
    let result = {
      message: 'OK',
      data: {
        availableVideos
      }
    };
    return Promise.resolve(result);
  }

  get (id, params) {
    return Promise.resolve({
      id, text: `A new message with ID: ${id}!`
    });
  }

  create (data, params) {
    let result = {
      message: 'OK',
      data
    };
    const watchRequest = {
      id: uuidv4(),
      body: JSON.stringify(data)
    };
    return new Promise ((resolve, reject) => {
      params.producer.send(watchRequest, error => {
        if (error) {
          const err = new errors.GeneralError('watch_request was not added to the queue', { error: error.message });
          reject(err);
        } else {
          resolve(result);
        }
      });
    });
  }

  update (id, data, params) {
    return Promise.resolve(data);
  }

  patch (id, data, params) {
    return Promise.resolve(data);
  }

  remove (id, params) {
    return Promise.resolve({ id });
  }
}

module.exports = function (options) {
  return new Service(options);
};

module.exports.Service = Service;

Change in catalog service to add items to SQS queue (id, body)


'use strict'

exports.config = {
  directConnect: true,

  allScriptsTimeout: 80000,

  specs: [
    'test/e2e/*.js'
  ],

  capabilities: {
    'browserName': 'chrome'
  },

  baseUrl: 'http://localhost:3000',

  framework: 'jasmine2',

  jasmineNodeOpts: {
    showColors: true,
    defaultTimeoutInterval: 80000
  },

  onPrepare: function () {
    var jasmineReporters = require('jasmine-reporters')
    jasmine.getEnv().addReporter(new jasmineReporters.JUnitXmlReporter({
      consolidateAll: true,
      savePath: 'build/reports/e2e_results'
    }))
  }
}

Add blank line at the end


/* Copyright © 2015 PointSource, LLC. All rights reserved. */
/*
 * Use the node-cors library to enable CORS on all express.js apps and endpoints.
 *
 * All config options are passed directly to the cors library.
 * See https://github.com/troygoode/node-cors#configuration-options
 */

var _ = require('lodash'),
    cors = require('cors');

var allowedOrigins = null;
var logger = null;

exports.init = function(app, config, logger, callback) {
    cfg = config.get('cors');
    allowedOrigins = cfg.allowOrigin;
    app.use(cors(cfg));
    logger.debug('Enabled CORS.');
    callback();
};

/* Copyright © 2015 PointSource, LLC. All rights reserved. */
/*
 * Use the node-cors library to enable CORS on all express.js apps and endpoints.
 *
 * All config options are passed directly to the cors library.
 * See https://github.com/troygoode/node-cors#configuration-options
 */

var _ = require('lodash'),
    cors = require('cors');

exports.init = function(app, config, logger, callback) {
    var cfg = config.get('cors');
    app.use(cors(cfg));
    logger.debug('Enabled CORS.');
    callback();
};

Remove unused code from CORS middleware


/**
 * A rate-limiting Throttle model, by IP address
 *
 */
var mongoose = require('mongoose')
var ipRegex = require('ip-regex')
var Schema = mongoose.Schema
mongoose.Promise = global.Promise
/**
 * Register the Throttle model
 *
 * @access public
 * @param {object} defaults
 * @return {object} Mongoose Model
 */
module.exports = function createThrottle (defaults) {
  var Throttle = new Schema({
    createdAt: {
      type: Date,
      required: true,
      default: Date.now,
      expires: defaults.rateLimit.ttl
    },
    ip: {
      type: String,
      required: true,
      trim: true,
      match: ipRegex
    },
    hits: {
      type: Number,
      default: 1,
      required: true,
      max: defaults.rateLimit.max,
      min: 0
    }
  })

  Throttle.index(
    { createdAt: 1 },
    { expireAfterSeconds: defaults.rateLimit.ttl }
  )

  return mongoose.model('Throttle', Throttle)
}

/**
 * A rate-limiting Throttle model, by IP address
 *
 */
var mongoose = require('mongoose')
var ipRegex = require('ip-regex')
var Schema = mongoose.Schema
mongoose.Promise = global.Promise
/**
 * Register the Throttle model
 *
 * @access public
 * @param {object} defaults
 * @return {object} Mongoose Model
 */
module.exports = function createThrottle (defaults) {
  var Throttle = new Schema({
    createdAt: {
      type: Date,
      required: true,
      default: Date.now,
      expires: defaults.rateLimit.ttl
    },
    ip: {
      type: String,
      required: true,
      trim: true,
      match: ipRegex()
    },
    hits: {
      type: Number,
      default: 1,
      required: true,
      max: defaults.rateLimit.max,
      min: 0
    }
  })

  Throttle.index(
    { createdAt: 1 },
    { expireAfterSeconds: defaults.rateLimit.ttl }
  )

  return mongoose.model('Throttle', Throttle)
}

Fix a typo in function call


import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { NavLink } from 'react-router-dom';
import './Sidenav.less';

const Sidenav = ({ username }) =>
  (

    {username &&

          <NavLink to={`/@${username}`} activeClassName="Sidenav__item--active">

            <FormattedMessage id="my_profile" defaultMessage="My profile" />
          </NavLink>

          <NavLink to="/" activeClassName="Sidenav__item--active" exact>

            <FormattedMessage id="feed" defaultMessage="Feed" />
          </NavLink>

          <NavLink to="/trending" activeClassName="Sidenav__item--active">

            <FormattedMessage id="news" defaultMessage="News" />
          </NavLink>

          <NavLink to="#wallet" activeClassName="Sidenav__item--active">

            <FormattedMessage id="wallet" defaultMessage="Wallet" />
          </NavLink>

}

);

Sidenav.propTypes = {
  username: PropTypes.string,
};

Sidenav.defaultProps = {
  username: undefined,
};

export default Sidenav;

import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
import { NavLink } from 'react-router-dom';
import './Sidenav.less';

const isNews = (match, location) => location.pathname !== '/';

const Sidenav = ({ username }) =>
  (

    {username &&

          <NavLink to={`/@${username}`} activeClassName="Sidenav__item--active">

            <FormattedMessage id="my_profile" defaultMessage="My profile" />
          </NavLink>

          <NavLink to="/" activeClassName="Sidenav__item--active" exact>

            <FormattedMessage id="feed" defaultMessage="Feed" />
          </NavLink>

          <NavLink to="/trending" activeClassName="Sidenav__item--active" isActive={isNews}>

            <FormattedMessage id="news" defaultMessage="News" />
          </NavLink>

          <NavLink to="#wallet" activeClassName="Sidenav__item--active">

            <FormattedMessage id="wallet" defaultMessage="Wallet" />
          </NavLink>

}

);

Sidenav.propTypes = {
  username: PropTypes.string,
};

Sidenav.defaultProps = {
  username: undefined,
};

export default Sidenav;

Add isNew function to determine if user is on news section


var HSCard = function(card) {
  this.id = card.id;
  this.cost = card.cost;
  this.attack = card.attack;
  this.health = card.health;
  this.quality = card.quality;
  this.name = card.name;
  this.description = card.description;
};

HSCard.prototype.getLink = function() {
  return HSCard.searchUrl + 'card=' + this.id;
};

HSCard.searchTerm = function(term) {
  return {
    url: HSCard.searchUrl + 'search?q=' + term,
    type: HSCard.searchType
  };
};

HSCard.searchType = 'hearthstonecards';

HSCard.searchUrl = 'http://www.hearthhead.com/';

module.exports = HSCard;

var HSCard = function(card) {
  this.id = card.id;
  this.cost = card.cost;
  this.attack = card.attack;
  this.health = card.health;
  this.quality = card.quality;
  this.name = card.name;
  this.description = card.description;
  this.durability = card.durability;
};

HSCard.prototype.getLink = function() {
  return HSCard.searchUrl + 'card=' + this.id;
};

HSCard.searchTerm = function(term) {
  return {
    url: HSCard.searchUrl + 'search?q=' + term,
    type: HSCard.searchType
  };
};

HSCard.searchType = 'hearthstonecards';

HSCard.searchUrl = 'http://www.hearthhead.com/';

module.exports = HSCard;

Add durability to card stats.


module.exports = {
    className: 'phone',
    template: require('./index.html'),
    data: {
        name: 'phone',
        icon: '/images/blocks_phone.png',
        attributes: {
            number: {
                label: 'Phone #',
                type: 'string',
                value: '+18005555555'
            },
            innerHTML: {
                label: 'Label',
                type: 'string',
                value: 'Place call'
            }
        }
    },
};

module.exports = {
    className: 'phone',
    template: require('./index.html'),
    data: {
        name: 'Phone',
        icon: '/images/blocks_phone.png',
        attributes: {
            number: {
                label: 'Phone #',
                type: 'string',
                value: '+18005555555'
            },
            innerHTML: {
                label: 'Label',
                type: 'string',
                value: 'Place call'
            }
        }
    },
};

Fix case on phone brick label


'use strict';

let angular = require('angular');

module.exports =  angular.module('spinnaker.pipelines.stage.determineTargetReferenceStage', [])
  .config(function(pipelineConfigProvider) {
    pipelineConfigProvider.registerStage({
      key: 'determineTargetReference',
      synthetic: true,
      executionDetailsUrl: require('./determineTargetReferenceDetails.html'),
    });
  })
  .name;

'use strict';

let angular = require('angular');

module.exports =  angular.module('spinnaker.pipelines.stage.determineTargetReferenceStage', [])
  .config(function(pipelineConfigProvider) {
    pipelineConfigProvider.registerStage({
      key: 'determineTargetServerGroup',
      synthetic: true,
      executionDetailsUrl: require('./determineTargetReferenceDetails.html'),
    });
  })
  .name;

Fix determine target reference stage


/*global Ghost, _ */
(function () {
    'use strict';
    //id:0 is used to issue PUT requests
    Ghost.Models.Settings = Ghost.ProgressModel.extend({
        url: Ghost.paths.apiRoot + '/settings/?type=blog,theme,app',
        id: '0',

        parse: function (response) {
            var result = _.reduce(response.settings, function (settings, setting) {
                settings[setting.key] = setting.value;

                return settings;
            }, {});

            return result;
        }
    });

}());

/*global Backbone, Ghost, _ */
(function () {
    'use strict';
    //id:0 is used to issue PUT requests
    Ghost.Models.Settings = Ghost.ProgressModel.extend({
        url: Ghost.paths.apiRoot + '/settings/?type=blog,theme,app',
        id: '0',

        parse: function (response) {
            var result = _.reduce(response.settings, function (settings, setting) {
                settings[setting.key] = setting.value;

                return settings;
            }, {});

            return result;
        },

        sync: function (method, model, options) {
            var settings = _.map(this.attributes, function (value, key) {
                return { key: key, value: value };
            });
            //wrap settings in {settings: [{...}]}
            if (method === 'update') {
                options.data = JSON.stringify({settings: settings});
                options.contentType = 'application/json';
            }

            return Backbone.Model.prototype.sync.apply(this, arguments);
        }
    });

}());

Move to new API format for Settings.


var play = require('../engine/play');
var Player = function(game, name) {
  this.name = name;
  this.inventory = null;
  this.chosen = false;
}

Player.prototype.populateInventory = function (constructSprite) {
  this.inventory = _.map(play.chooseIngredients(4), function(name) {
    return {
      name : name,
      sprite : constructSprite(name)
    }
  });
}

Player.prototype.addIngredient = function (food, plate) {
  this.removeFromInventory(this.inventory, food);
  plate.foods.push(food.name);
  plate.update();
}

Player.prototype.removeFromInventory = function (inventory, food) {
  food.sprite.alpha = .1;
}

Player.prototype.choose = function (index) {
  // var foodIndex = getIndex(sprite.xDif, sprite.yDif);
  var food = this.inventory[index];
  this.addIngredient(food, plates[0]);
  console.log('%s selected %s', this.name, food.name);
  this.chosen = true;
     /*var tween = this.game.add.tween(newFood, this.game, this.game.tweens);
  //   tween.to({
  //     x: 200,
  //     y: 0
  //   });
  //   tween.start();*/

  //   /*tween.onComplete = function(target, tween) {
  //     target.kill();
  //   }*/
  // }
}

module.exports = Player;

var play = require('../engine/play');
var Player = function(game, name) {
  this.name = name;
  this.inventory = null;
  this.chosen = false;
}

Player.prototype.populateInventory = function (constructSprite) {
  this.inventory = _.map(play.chooseIngredients(4), function(name) {
    return {
      name : name,
      sprite : constructSprite(name)
    }
  });
}

Player.prototype.addIngredient = function (food, plate) {
  this.removeFromInventory(food);
  plate.foods.push(food.name);
  plate.update();
}

Player.prototype.removeFromInventory = function (food) {
  food.sprite.alpha = 0;
  var index = _(this.inventory).findIndex({name : food.name});
  this.inventory.splice(index, 1);
}

Player.prototype.choose = function (index) {
  var food = this.inventory[index];
  this.addIngredient(food, plates[0]);
  console.log('%s selected %s', this.name, food.name);
  this.chosen = true;
     /*var tween = this.game.add.tween(newFood, this.game, this.game.tweens);
  //   tween.to({
  //     x: 200,
  //     y: 0
  //   });
  //   tween.start();*/

  //   /*tween.onComplete = function(target, tween) {
  //     target.kill();
  //   }*/
  // }
}

module.exports = Player;

Remove from inventory on select


function Scratch3ControlBlocks(runtime) {
    /**
     * The runtime instantiating this block package.
     * @type {Runtime}
     */
    this.runtime = runtime;
}

/**
 * Retrieve the block primitives implemented by this package.
 * @return {Object.<string, Function>} Mapping of opcode to Function.
 */
Scratch3ControlBlocks.prototype.getPrimitives = function() {
    return {
        'control_repeat': this.repeat,
        'control_forever': this.forever,
        'control_wait': this.wait,
        'control_stop': this.stop
    };
};

Scratch3ControlBlocks.prototype.repeat = function(argValues, util) {
    // Initialize loop
    if (util.stackFrame.loopCounter === undefined) {
        util.stackFrame.loopCounter = parseInt(argValues[0]); // @todo arg
    }
    // Decrease counter
    util.stackFrame.loopCounter--;
    // If we still have some left, start the substack
    if (util.stackFrame.loopCounter >= 0) {
        util.startSubstack();
    }
};

Scratch3ControlBlocks.prototype.forever = function(argValues, util) {
    util.startSubstack();
};

Scratch3ControlBlocks.prototype.wait = function(argValues, util) {
    util.yield();
    util.timeout(function() {
        util.done();
    }, 1000 * argValues.DURATION);
};

Scratch3ControlBlocks.prototype.stop = function() {
    // @todo - don't use this.runtime
    this.runtime.stopAll();
};

module.exports = Scratch3ControlBlocks;

function Scratch3ControlBlocks(runtime) {
    /**
     * The runtime instantiating this block package.
     * @type {Runtime}
     */
    this.runtime = runtime;
}

/**
 * Retrieve the block primitives implemented by this package.
 * @return {Object.<string, Function>} Mapping of opcode to Function.
 */
Scratch3ControlBlocks.prototype.getPrimitives = function() {
    return {
        'control_repeat': this.repeat,
        'control_forever': this.forever,
        'control_wait': this.wait,
        'control_stop': this.stop
    };
};

Scratch3ControlBlocks.prototype.repeat = function(argValues, util) {
    // Initialize loop
    if (util.stackFrame.loopCounter === undefined) {
        util.stackFrame.loopCounter = parseInt(argValues.TIMES);
    }
    // Decrease counter
    util.stackFrame.loopCounter--;
    // If we still have some left, start the substack
    if (util.stackFrame.loopCounter >= 0) {
        util.startSubstack();
    }
};

Scratch3ControlBlocks.prototype.forever = function(argValues, util) {
    util.startSubstack();
};

Scratch3ControlBlocks.prototype.wait = function(argValues, util) {
    util.yield();
    util.timeout(function() {
        util.done();
    }, 1000 * argValues.DURATION);
};

Scratch3ControlBlocks.prototype.stop = function() {
    // @todo - don't use this.runtime
    this.runtime.stopAll();
};

module.exports = Scratch3ControlBlocks;

Fix argument for repeat block


import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import { TileLayer } from 'react-leaflet'

class RoutesOverlay extends Component {
  static propTypes = {
  }

  render () {
    return (
      <TileLayer
        url='https://d2dyq00q2cz8yt.cloudfront.net/{z}_{x}_{y}@2x.png'
      />
    )
  }
}

// connect to the redux store

const mapStateToProps = (state, ownProps) => {
  // TODO: pass in tileset via config
  return { }
}

const mapDispatchToProps = { }

export default connect(mapStateToProps, mapDispatchToProps)(RoutesOverlay)

import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import { TileLayer } from 'react-leaflet'

class RoutesOverlay extends Component {
  static propTypes = {
    tileUrl: PropTypes.string
  }

  render () {
    return this.props.tileUrl
      ? <TileLayer url={this.props.tileUrl} />
      : null
  }
}

// connect to the redux store

const mapStateToProps = (state, ownProps) => {
  // TODO: pass in tileset via config
  return {
    tileUrl:
      state.otp.config.map &&
      state.otp.config.map.routesOverlay &&
      state.otp.config.map.routesOverlay.tileUrl
        ? state.otp.config.map.routesOverlay.tileUrl
        : null
  }
}

const mapDispatchToProps = { }

export default connect(mapStateToProps, mapDispatchToProps)(RoutesOverlay)

Make route overlay url configurable


import express from 'express';
import ip      from 'ip';

import leftpad from './left-pad';

const app  = express();
const port = process.env.PORT || 3000;

app.get('/', (req, res, next) => {
    let str = req.query.str;
    const ch  = req.query.ch;
    const len = req.query.len;

    typeof str === 'undefined' ? str = '' : str = str;
    res.status(200).json({ str: leftpad(str, len, ch) });
});

if (!module.parent) {
    app.listen(port, () => {
        console.log(`Express app running at ${ip.address()}:${port}`);
    });
}

export default app;

import express from 'express';
import ip      from 'ip';

import leftpad from './left-pad';

const app  = express();
const port = process.env.PORT || 3000;

app.get('/', (req, res) => {
    let   str = req.query.str;
    const ch  = req.query.ch;
    const len = req.query.len;

    if (typeof str === 'undefined') str = '';

    res.status(200).json({ str: leftpad(str, len, ch) });
});

if (!module.parent) {
    app.listen(port, () => {
        console.log(`Express app running at ${ip.address()}:${port}`);
    });
}

export default app;

Add even better check for undefined str parameter


import { Template } from 'meteor/templating';

import '/imports/ui/components/ticket/ticket.js';

import './queue-table.html';

Template.QueueTable.helpers({
  noActiveTickets(queue) {
    return queue.activeTickets().count() === 0;
  },

  rows(queue) {
    const rows = [];

    const tickets = queue.tickets().fetch();
    tickets.forEach((ticket, i) => {
      if (ticket.isActive()) {
        ticket.index = i + 1; // eslint-disable-line no-param-reassign
        rows.push(ticket);
      }

      if (queue.isCutoff() && (ticket._id === queue.cutoffAfter)) {
        rows.push({
          isCutoffMarker: true,
        });
      }
    });

    return rows;
  },
});

import { Template } from 'meteor/templating';

import '/imports/ui/components/ticket/ticket.js';

import './queue-table.html';

Template.QueueTable.helpers({
  noActiveTickets(queue) {
    return queue.activeTickets().count() === 0;
  },

  rows(queue) {
    let index = 1;
    const rows = [];

    const tickets = queue.tickets().fetch();
    tickets.forEach((ticket) => {
      if (ticket.isActive()) {
        ticket.index = index; // eslint-disable-line no-param-reassign
        rows.push(ticket);
        index += 1;
      }

      if (queue.isCutoff() && (ticket._id === queue.cutoffAfter)) {
        rows.push({
          isCutoffMarker: true,
        });
      }
    });

    return rows;
  },
});

Fix indexing in active tickets


import { shallow, mount } from 'enzyme';
import React from 'react';
import assert from 'assert';
import ComboEditor from './editor';
import { workflow } from '../../../pages/dev-classifier/mock-data';

const task = {
  type: 'combo',
  loosen_requirements: true,
  tasks: ['write', 'ask', 'features', 'draw', 'survey', 'slider']
};

describe('ComboEditor', function () {
  it('should render for a workflow and task', () => {
    const wrapper = shallow(<ComboEditor workflow={workflow} task={task} />);
    assert.equal(wrapper.instance() instanceof ComboEditor, true);
  });
});

describe('deleting a workflow task', () => {
  const workflowCopy = Object.assign({}, workflow);
  const tasks = Object.assign({}, workflow.tasks);
  delete tasks.ask;
  workflowCopy.tasks = tasks;
  it('should render and update the combo task', () => {
    const wrapper = mount(<ComboEditor workflow={workflowCopy} task={task} />);
    const { props } = wrapper.instance();
    assert.equal(props.task.tasks.indexOf('ask'), -1);
  });
});

import { mount } from 'enzyme';
import React from 'react';
import assert from 'assert';
import ComboEditor from './editor';
import { workflow } from '../../../pages/dev-classifier/mock-data';

const task = {
  type: 'combo',
  loosen_requirements: true,
  tasks: ['write', 'ask', 'features', 'draw', 'survey', 'slider']
};

describe('ComboEditor', () => {
  const wrapper = mount(<ComboEditor workflow={workflow} task={task} />);

  it('should render for a workflow and task', () => {
    assert.equal(wrapper.instance() instanceof ComboEditor, true);
  });

  it('should add new tasks to the combo when selected', () => {
    wrapper.find('select[value="stuck"]').simulate('change', { target: { value: 'dropdown' }});
    const { props } = wrapper.instance();
    assert.notEqual(props.task.tasks.indexOf('dropdown'), -1);
  });

  it('should allow tasks to be deleted from the combo', () => {
    wrapper.find('ul.drag-reorderable button').first().simulate('click');
    const { props } = wrapper.instance();
    assert.equal(props.task.tasks.indexOf('write'), -1);
  });
});

describe('deleting a workflow task', () => {
  const workflowCopy = Object.assign({}, workflow);
  const tasks = Object.assign({}, workflow.tasks);
  delete tasks.ask;
  workflowCopy.tasks = tasks;
  it('should render and update the combo task', () => {
    const wrapper = mount(<ComboEditor workflow={workflowCopy} task={task} />);
    const { props } = wrapper.instance();
    assert.equal(props.task.tasks.indexOf('ask'), -1);
  });
});

Add combo editor tests Add tests for adding and deleting a task from the combo task.


import { extend } from 'flarum/extend';
import LinkButton from 'flarum/components/LinkButton';
import IndexPage from 'flarum/components/IndexPage';
import DiscussionList from 'flarum/components/DiscussionList';

export default function addSubscriptionFilter() {
  extend(IndexPage.prototype, 'navItems', function(items) {
    if (app.session.user) {
      const params = this.stickyParams();

      params.filter = 'following';

      items.add('following', LinkButton.component({
        href: app.route('index.filter', params),
        children: app.translator.trans('flarum-subscriptions.forum.index.following_link'),
        icon: 'fas fa-star'
      }), 50);
    }
  });

  extend(IndexPage.prototype, 'config', function () {
    if (m.route() == "/following") {
      app.setTitle(app.translator.trans('flarum-subscriptions.forum.following.meta_title_text'));
    }
  });

  extend(DiscussionList.prototype, 'requestParams', function(params) {
    if (this.props.params.filter === 'following') {
      params.filter.q = (params.filter.q || '') + ' is:following';
    }
  });
}

import { extend } from 'flarum/extend';
import LinkButton from 'flarum/components/LinkButton';
import IndexPage from 'flarum/components/IndexPage';
import DiscussionListState from 'flarum/states/DiscussionListState';

export default function addSubscriptionFilter() {
  extend(IndexPage.prototype, 'navItems', function(items) {
    if (app.session.user) {
      const params = this.stickyParams();

      params.filter = 'following';

      items.add('following', LinkButton.component({
        href: app.route('index.filter', params),
        children: app.translator.trans('flarum-subscriptions.forum.index.following_link'),
        icon: 'fas fa-star'
      }), 50);
    }
  });

  extend(IndexPage.prototype, 'config', function () {
    if (m.route() == "/following") {
      app.setTitle(app.translator.trans('flarum-subscriptions.forum.following.meta_title_text'));
    }
  });

  extend(DiscussionListState.prototype, 'requestParams', function(params) {
    if (this.params.filter === 'following') {
      params.filter.q = (params.filter.q || '') + ' is:following';
    }
  });
}

Fix extension to work with latest state changes


'use strict';

import chai, { expect } from 'chai';
import sinon from 'sinon';
import { default as sinonChai } from 'sinon-chai';
import 'sinon-as-promised';

require('../../../angular-test-helper');
require('browser/main');

chai.use(sinonChai);

describe('LocationController', function() {
  describe('initial state', function() {
    beforeEach(ngModule('devPlatInstaller'));

    var $controller;

    beforeEach(inject(function(_$controller_) {
    // The injector unwraps the underscores (_) from around the parameter names when matching
      $controller = _$controller_;
    }));

    it('sets correct default target install location', function() {
      let $watch = sinon.stub();
      let $scope = {$watch};
      let ctrl = $controller('LocationController', { $scope });
      expect(ctrl.folder).to.be.equal(ctrl.installerDataSvc.installDir());
    });

  });
});

'use strict';

import LocationController from 'browser/pages/location/controller';
import InstallerDataService from 'browser/services/data';
import chai, { expect } from 'chai';
import sinon from 'sinon';
import { default as sinonChai } from 'sinon-chai';
import 'sinon-as-promised';

require('../../../angular-test-helper');
require('browser/main');

chai.use(sinonChai);

describe('LocationController', function() {

  let sandbox, locationcontroller, scope, timeout;
  let installerDataSvc;

  beforeEach(function() {

    scope = { '$apply': function() { } };
    timeout = function(cb) { cb(); };
    sandbox = sinon.sandbox.create();
    installerDataSvc = sinon.stub(new InstallerDataService());
    locationcontroller = new LocationController(scope, {}, timeout, installerDataSvc);
  });

  afterEach(function() {
    sandbox.restore();
  });

  describe('initial state', function() {
    beforeEach(ngModule('devPlatInstaller'));

    var $controller;

    beforeEach(inject(function(_$controller_) {
    // The injector unwraps the underscores (_) from around the parameter names when matching
      $controller = _$controller_;
    }));

    it('sets correct default target install location', function() {
      let $watch = sinon.stub();
      let $scope = {$watch};
      let ctrl = $controller('LocationController', { $scope });
      expect(ctrl.folder).to.be.equal(ctrl.installerDataSvc.installDir());
    });

  });

  describe('checkFolder', function(){
    it('should able to check folder exist status', function(){
      locationcontroller.checkFolder();
      expect(locationcontroller.folderExists).to.be.equal(false);

    });
  });
});

Increase unit tests code coverage controller location


Test the alerting system on pages new


var siteUrl = 'http://example.org';

casper.test.setUp(function globalSetUp() {
    phantom.clearCookies();
});

var
    siteUrl = 'http://example.org',
    env     = require('system').env
;

casper.test.setUp(function globalSetUp() {
    phantom.clearCookies();
});

Declare environment as a variable


import queryString from 'query-string'
import events from '../core/events'
import * as constants from '../constants'
import { actions } from '../store/actions'
import ReconnectingWebSocket from 'reconnectingwebsocket'

const {
  setDocumentCaptured,
  setToken,
  setAuthenticated
} = actions

export default class Socket {

  connect(jwt) {
    const query = queryString.stringify({ jwt: jwt })
    const url = `${constants.DEV_SOCKET_URL}?${query}`
    const socket = new ReconnectingWebSocket(url)
    socket.onopen = () => {
      this.socket = socket
      this.onMessage()
      setToken(jwt)
      setAuthenticated(true)
    }
  }

  handleData(data) {
    events.emit('onMessage', data)
    if (data.is_document) {
      setDocumentCaptured(true)
    }
  }

  onMessage() {
    this.socket.onmessage = (e) => {
      const data = JSON.parse(e.data)
      this.handleData(data)
    }
  }

  sendMessage(message) {
    this.socket.send(message)
  }

}

import queryString from 'query-string'
import events from '../core/events'
import * as constants from '../constants'
import { actions } from '../store/actions'
import ReconnectingWebSocket from 'reconnectingwebsocket'

const {
  setDocumentCaptured,
  setToken,
  setAuthenticated
} = actions

export default class Socket {

  connect(jwt) {
    const query = queryString.stringify({ jwt: jwt })
    const url = `${constants.DEV_SOCKET_URL}?${query}`
    const socket = new ReconnectingWebSocket(url)
    socket.onopen = () => {
      this.socket = socket
      this.onMessage()
      setToken(jwt)
      setAuthenticated(true)
    }
  }

  onMessage() {
    this.socket.onmessage = (e) => {
      const data = JSON.parse(e.data)
      events.emit('onMessage', data)
    }
  }

  sendMessage(message) {
    this.socket.send(message)
  }

}

Move message handling out of core


$( document ).on('turbolinks:load', function() {
	if ($('#desktopTest').is(':hidden')) {
	    	$('.desktop').attr("hidden", true);
		} else {
				$('.mobile').attr("hidden", true);
		}
})

$( document ).on('turbolinks:load', function() {
	if ($('#desktopTest').is(':hidden')) {
	    	$('.desktop').remove();
		} else {
				$('.mobile').remove();
		}
})

Remove unused templates from DOM instead of hiding


/* Check if OS name is Windows and if wireless connection is available */
if (org.ow2.proactive.scripting.helper.selection.SelectionUtils.checkOSName("windows") && SelectionUtils.checkWifi()){
    selected = true;
} else {
    selected = false;
}

/* Check if OS name is Windows and if wireless connection is available */
if (org.ow2.proactive.scripting.helper.selection.SelectionUtils.checkOSName("windows")
        && org.ow2.proactive.scripting.helper.selection.SelectionUtils.checkWifi()){
    selected = true;
} else {
    selected = false;
}

Add missing package name for usage of SelectionUtils in a sample


import {exec} from 'child_process';

import semver from 'semver';

const {major, minor, patch} = semver.parse(atom.appVersion);
const atomVersion = `${major}.${minor}.${patch}`;
const requiredVersion = '>=1.14.0';

import GitPromptServer from '../lib/git-prompt-server';

// Will not pass on Appveyor
if (process.platform !== 'win32' && semver.satisfies(atomVersion, requiredVersion)) {
  describe('GitPromptServer', function() {
    it('prompts for user input and writes the response to stdout', async function() {
      this.timeout(10000);

      const server = new GitPromptServer();
      const {helper, socket, electron} = await server.start(question => {
        assert.equal(question, 'What... is your favorite color?\u0000');
        return 'Green. I mean blue! AAAhhhh...';
      });

      let err, stdout;
      await new Promise((resolve, reject) => {
        const command = `"${electron}" "${helper}" "${socket}" "What... is your favorite color?"`;
        exec(command, {
          env: {
            ELECTRON_RUN_AS_NODE: 1,
            ELECTRON_NO_ATTACH_CONSOLE: 1,
          },
        }, (_err, _stdout, _stderr) => {
          err = _err;
          stdout = _stdout;
          resolve();
        });
      });

      assert.ifError(err);
      assert.equal(stdout, 'Green. I mean blue! AAAhhhh...\n');

      await server.terminate();
    });
  });
}

import {execFile} from 'child_process';

import semver from 'semver';

const {major, minor, patch} = semver.parse(atom.appVersion);
const atomVersion = `${major}.${minor}.${patch}`;
const requiredVersion = '>=1.14.0';

import GitPromptServer from '../lib/git-prompt-server';

// Will not pass on Appveyor
if (process.platform !== 'win32' && semver.satisfies(atomVersion, requiredVersion)) {
  describe('GitPromptServer', function() {
    it('prompts for user input and writes the response to stdout', async function() {
      this.timeout(10000);

      const server = new GitPromptServer();
      const {helper, socket, electron} = await server.start(question => {
        assert.equal(question, 'What... is your favorite color?\u0000');
        return 'Green. I mean blue! AAAhhhh...';
      });

      let err, stdout;
      await new Promise((resolve, reject) => {
        execFile(electron,
          [helper, socket, 'What... is your favorite color?'],
          {
            env: {
              ELECTRON_RUN_AS_NODE: 1,
              ELECTRON_NO_ATTACH_CONSOLE: 1,
            },
          }, (_err, _stdout, _stderr) => {
            err = _err;
            stdout = _stdout;
            resolve();
          });
      });

      assert.ifError(err);
      assert.equal(stdout, 'Green. I mean blue! AAAhhhh...\n');

      await server.terminate();
    });
  });
}

Use `execFile` instead of `exec`


const DrawCard = require('../../drawcard.js');

class WholenessOfTheWorld extends DrawCard {
    setupCardAbilities() {
        this.wouldInterrupt({
            title: 'Keep a claimed ring',
            when: {
                onReturnRing: (event, context) => event.ring.claimedBy === context.player.name
            },
            cannotBeMirrored: true,
            effect: 'prevent {1} from returning to the unclaimed pool',
            effectArgs: context => context.event.ring,
            handler: context => context.cancel()
        });
    }
}

WholenessOfTheWorld.id = 'wholeness-of-the-world';

module.exports = WholenessOfTheWorld;

const DrawCard = require('../../drawcard.js');

class WholenessOfTheWorld extends DrawCard {
    setupCardAbilities(ability) {
        this.wouldInterrupt({
            title: 'Keep a claimed ring',
            when: {
                onReturnRing: (event, context) => event.ring.claimedBy === context.player.name
            },
            cannotBeMirrored: true,
            effect: 'prevent {1} from returning to the unclaimed pool',
            effectArgs: context => context.event.ring,
            handler: context => context.cancel(),
            max: ability.limit.perRound(1)
        });
    }
}

WholenessOfTheWorld.id = 'wholeness-of-the-world';

module.exports = WholenessOfTheWorld;

Fix Wholeness of the World to be max 1 per round


// @flow

import {AppRegistry, YellowBox} from 'react-native'
import App from './app'

YellowBox.ignoreWarnings([
	'Failed prop type: Invalid prop `containerTagName` of type `object` supplied to `ReactMarkdown`, expected `function`',
])

AppRegistry.registerComponent('AllAboutOlaf', () => App)

// @flow

import {AppRegistry, YellowBox} from 'react-native'
import App from './app'

YellowBox.ignoreWarnings([
	'Failed prop type: Invalid prop `containerTagName` of type `object` supplied to `ReactMarkdown`, expected `function`',
	'Failed prop type: Invalid prop `containerTagName` of type `string` supplied to `ReactMarkdown`, expected `function`.',
	"MaskedViewIOS has been extracted from react-native core and will be removed in a future release. It can now be installed and imported from '@react-native-community/masked-view' instead of 'react-native'. See https://github.com/react-native-community/react-native-masked-view",
	'componentWillReceiveProps has been renamed, and is not recommended for use. See https://fb.me/react-async-component-lifecycle-hooks for details.',
	'componentWillMount has been renamed, and is not recommended for use. See https://fb.me/react-async-component-lifecycle-hooks for details.',
])

AppRegistry.registerComponent('AllAboutOlaf', () => App)

Add to list of ignored yellowbox warnings


window.onerror = function(message, url, line) {
    $.ajax('/api/Error', {
        data: {
            message: message,
            url: url,
            line: line
        }
    });
};

window.onerror = function(message, url, line) {
    // Don't attempt to handle non-standard errors (e.g. failed
    // HTTP request via jQuery).
    if (typeof message !== 'string') return;
    $.ajax('/api/Error', {
        data: {
            message: message,
            url: url,
            line: line
        }
    });
};

Fix for failure to serialize jQuery event object.


// Karma configuration file, see link for more information
// https://karma-runner.github.io/0.13/config/configuration-file.html

module.exports = function (config) {
    config.set({
        basePath: '../../',
        frameworks: ['jasmine', '@angular/cli'],
        plugins: [
            require('karma-jasmine'),
            require('karma-chrome-launcher'),
            require('karma-jasmine-html-reporter'),
            require('karma-coverage-istanbul-reporter'),
            require('@angular/cli/plugins/karma')
        ],
        client: {
            clearContext: false // leave Jasmine Spec Runner output visible in browser
        },
        coverageIstanbulReporter: {
            reports: ['html', 'lcovonly'],
            fixWebpackSourcePaths: true
        },
        angularCli: {
            environment: 'dev'
        },
        reporters: ['progress', 'kjhtml'],
        port: 9876,
        colors: true,
        logLevel: config.LOG_INFO,
        autoWatch: true,
        browsers: ['Chrome'],
        singleRun: false
    });
};

// Karma configuration file, see link for more information
// https://karma-runner.github.io/0.13/config/configuration-file.html

module.exports = function (config) {
    config.set({
        basePath: '../../',
        frameworks: ['jasmine', '@angular/cli'],
        plugins: [
            require('karma-jasmine'),
            require('karma-chrome-launcher'),
            require('karma-jasmine-html-reporter'),
            require('karma-coverage-istanbul-reporter'),
            require('@angular/cli/plugins/karma')
        ],
        client: {
            clearContext: false // leave Jasmine Spec Runner output visible in browser
        },
        coverageIstanbulReporter: {
            reports: ['html', 'lcovonly'],
            fixWebpackSourcePaths: true
        },
        angularCli: {
            environment: 'dev'
        },
        reporters: ['progress', 'kjhtml'],
        port: 9876,
        colors: true,
        logLevel: config.LOG_INFO,
        autoWatch: true,
        browsers: ['Chrome'],
        singleRun: true
    });
};

Change test to only run once


const fs = require('fs-extra'),
    Path = require('path');

var _settings = { // Private storage of settings
        global: {},
        local: {}
    },
    _currPath; // Path to the settings.json file

var Settings = {

    GetGlobal: (name) => {
        if(!_settings.global) _settings.global = {};
        return _settings.global[name] || null;
    },
    GetLocal: (name) => {
        if(!_settings.local) _settings.local = {};
        return _settings.local[name] || null;
    },
    SetGlobal: (name, data) =>  { _settings.global[name] = data; },
    SetLocal: (name, data) =>   { _settings.local[name] = data; },

    Save: function() {
        fs.ensureFileSync(_currPath);
        fs.writeJsonSync(_currPath, _settings);
    },

    Load: function(dir) {
        // Load the settings into memory
        _currPath = Path.resolve(dir, 'settings.json');

        if(!fs.existsSync(_currPath)) {
            // Ensure the settings.json file exists with
            // at least empty `global` and `local` objects
            fs.writeFileSync(_currPath, '{"global": {}, "local": {}}');
        }

        _settings = fs.readJsonSync(_currPath);
    }

}

module.exports = Settings;

const fs = require('fs-extra'),
    Path = require('path');

var _settings = { // Private storage of settings
        global: {
            recentMaps: []
        },
        local: {}
    },
    _currPath; // Path to the settings.json file

var Settings = {

    GetGlobal: (name) => {
        if(!_settings.global) _settings.global = {};
        return _settings.global[name] || null;
    },
    GetLocal: (name) => {
        if(!_settings.local) _settings.local = {};
        return _settings.local[name] || null;
    },
    SetGlobal: (name, data) =>  { _settings.global[name] = data; },
    SetLocal: (name, data) =>   { _settings.local[name] = data; },

    Save: function() {
        fs.ensureFileSync(_currPath);
        fs.writeJsonSync(_currPath, _settings);
    },

    Load: function(dir) {
        // Load the settings into memory
        _currPath = Path.resolve(dir, 'settings.json');

        if(!fs.existsSync(_currPath)) {
            // Ensure the settings.json file exists with
            // at least empty `global` and `local` objects
            console.log('Settings.json file is missing; writing & using default empty file', _settings);
            fs.writeJsonSync(_currPath, _settings);
        }

        _settings = fs.readJsonSync(_currPath);
    }

}

module.exports = Settings;

Improve handling of missing settings file


Template.postsList.helpers({
  posts: function() {
    return Posts.find();
  }
});

Template.postsList.helpers({
  posts: function() {
    return Posts.find({}, {sort: {submitted: -1}});
  }
});

Sort posts by submitted timestamp.


#!/usr/bin/env node
'use strict'

const join = require('path').join
const minimist = require('minimist')
const GitAddAndCommit = require(join(__dirname, '../'))

const CLI_OPTIONS = ['caseSensitive', 'help', 'interactive']

let argv = minimist(process.argv.slice(2), {
	alias: {
		c: 'caseSensitive',
		h: 'help',
		i: 'interactive',
		'case-sensitive': 'caseSensitive'
	},
	boolean: CLI_OPTIONS
})

let options = {}
for (let option of CLI_OPTIONS) {
	options[option] = argv[option]
}

new GitAddAndCommit(options)

#!/usr/bin/env node
'use strict'

const join = require('path').join
const minimist = require('minimist')
const GitAddAndCommit = require(join(__dirname, '../'))

let booleans = {
	c: 'caseSensitive',
	h: 'help',
	i: 'interactive'
}

let needArgs = {
	e: 'except',
	o: 'only'
}

const CLI_OPTIONS = Object.assign({}, booleans, needArgs)

let argv = minimist(process.argv.slice(2), {
	alias: CLI_OPTIONS,
	boolean: Object.keys(booleans).map(key => booleans[key])
})

let options = {}
setupOptions(options)
parseFilesToFind(options)
new GitAddAndCommit(options)

//
// Helpers
//
function setupOptions(options) {
	for (let option of Object.keys(booleans).map(key => booleans[key])) {
		options[option] = argv[option]
	}
}

function parseFilesToFind(options) {
	let _letterToFileMap = {
		d: 'deleted',
		m: 'modified',
		s: 'staged',
		u: 'untracked'
	}

	// defaults
	let find = {
		deleted: true,
		modified: true,
		staged: true,
		untracked: true
	}

	for (let file of argv.except && argv.except.split(',') || []) { // that's a cool line
		delete find[_letterToFileMap[file[0] && file[0].toLowerCase()]] // another cool line
	}

	// need to delete all find files if `argv.only` is present
	find = argv.only ? {} : find

	for (let file of argv.only && argv.only.split(',') || []) {
		find[_letterToFileMap[file[0].toLowerCase()]] = true
	}

	options.find = find
}

Add --only and --except options for which git file types to look for


/* @flow */

import mergeWith from "lodash/mergeWith";

export default function (dest?: Object, src?: Object): ?Object {
  if (!dest || !src) return;

  return mergeWith(dest, src, function (a, b) {
    if (b && Array.isArray(a)) {
      let newArray = b.slice(0);

      for (let item of a) {
        if (newArray.indexOf(item) < 0) {
          newArray.push(item);
        }
      }

      return newArray;
    }
  });
}

/* @flow */

import mergeWith from "lodash/mergeWith";
import union from "lodash/union";

// Deeply merges two objects, ignoring null and undefined, and unions arrays
// TODO: see if this can just be replaced with lodash v4 merge
export default function (dest?: Object, src?: Object): ?Object {
  if (!dest || !src) return;

  return mergeWith(dest, src, function (a, b) {
    if (b && Array.isArray(a)) {
      return union(b, a);
    }
  });
}

Replace custom union code with lodash union


/**
 * Bahasa translation for bootstrap-datetimepicker
 * Azwar Akbar <azwar.akbar@gmail.com>
 */
;(function($){
	$.fn.datetimepicker.dates['id'] = {
		days: ["Minggu", "Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu", "Minggu"],
		daysShort: ["Mgu", "Sen", "Sel", "Rab", "Kam", "Jum", "Sab", "Mgu"],
		daysMin: ["Mg", "Sn", "Sl", "Ra", "Ka", "Ju", "Sa", "Mg"],
		months: ["Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "November", "Desember"],
		monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Ags", "Sep", "Okt", "Nov", "Des"],
		suffix: [],
		meridiem: []
	};
}(jQuery));

/**
 * Bahasa translation for bootstrap-datetimepicker
 * Azwar Akbar <azwar.akbar@gmail.com>
 */
;(function($){
	$.fn.datetimepicker.dates['id'] = {
		days: ["Minggu", "Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu", "Minggu"],
		daysShort: ["Mgu", "Sen", "Sel", "Rab", "Kam", "Jum", "Sab", "Mgu"],
		daysMin: ["Mg", "Sn", "Sl", "Ra", "Ka", "Ju", "Sa", "Mg"],
		months: ["Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "November", "Desember"],
		monthsShort: ["Jan", "Feb", "Mar", "Apr", "Mei", "Jun", "Jul", "Ags", "Sep", "Okt", "Nov", "Des"],
		today: "Hari Ini",
		suffix: [],
		meridiem: []
	};
}(jQuery));

Add 'today' translation for Bahasa


/**
 * util-events.js - The minimal events support
 */

var events = data.events = {}

// Bind event
seajs.on = function(name, callback) {
  var list = events[name] || (events[name] = [])
  list.push(callback)
  return seajs
}

// Remove event. If `callback` is undefined, remove all callbacks for the
// event. If `event` and `callback` are both undefined, remove all callbacks
// for all events
seajs.off = function(name, callback) {
  // Remove *all* events
  if (!(name || callback)) {
    data.events = events = {}
    return seajs
  }

  var list = events[name]
  if (list) {
    if (callback) {
      for (var i = list.length - 1; i >= 0; i--) {
        if (list[i] === callback) {
          list.splice(i, 1)
        }
      }
    }
    else {
      delete events[name]
    }
  }

  return seajs
}

// Emit event, firing all bound callbacks. Callbacks are passed the same
// arguments as `emit` is, apart from the event name
var emit = seajs.emit = function(name, data) {
  var list = events[name], fn

  if (list) {
    // Copy callback lists to prevent modification
    list = list.slice()

    // Execute event callbacks
    while ((fn = list.shift())) {
      fn(data)
    }
  }

  return seajs
}

/**
 * util-events.js - The minimal events support
 */

var events = data.events = {}

// Bind event
seajs.on = function(name, callback) {
  var list = events[name] || (events[name] = [])
  list.push(callback)
  return seajs
}

// Remove event. If `callback` is undefined, remove all callbacks for the
// event. If `event` and `callback` are both undefined, remove all callbacks
// for all events
seajs.off = function(name, callback) {
  // Remove *all* events
  if (!(name || callback)) {
    for (var prop in events) {
      delete events[prop]
    }
    return seajs
  }

  var list = events[name]
  if (list) {
    if (callback) {
      for (var i = list.length - 1; i >= 0; i--) {
        if (list[i] === callback) {
          list.splice(i, 1)
        }
      }
    }
    else {
      delete events[name]
    }
  }

  return seajs
}

// Emit event, firing all bound callbacks. Callbacks are passed the same
// arguments as `emit` is, apart from the event name
var emit = seajs.emit = function(name, data) {
  var list = events[name], fn

  if (list) {
    // Copy callback lists to prevent modification
    list = list.slice()

    // Execute event callbacks
    while ((fn = list.shift())) {
      fn(data)
    }
  }

  return seajs
}

Fix a bug in Node.js


/**
 * Bootstrap
 * (sails.config.bootstrap)
 *
 * An asynchronous bootstrap function that runs before your Sails app gets lifted.
 * This gives you an opportunity to set up your data model, run jobs, or perform some special logic.
 *
 * For more information on bootstrapping your app, check out:
 * http://sailsjs.org/#!/documentation/reference/sails.config/sails.config.bootstrap.html
 */

module.exports.bootstrap = function(cb) {

  Video.findOne({
    playing: true
  }).then(function(err, current) {
    if (current) {
      SyncService.startVideo(current);
    }
    cb();
  });
};

/**
 * Bootstrap
 * (sails.config.bootstrap)
 *
 * An asynchronous bootstrap function that runs before your Sails app gets lifted.
 * This gives you an opportunity to set up your data model, run jobs, or perform some special logic.
 *
 * For more information on bootstrapping your app, check out:
 * http://sailsjs.org/#!/documentation/reference/sails.config/sails.config.bootstrap.html
 */

module.exports.bootstrap = function(cb) {

  Video.findOne({
    playing: true
  }).then(function(current, err) {
    if (current) {
      SyncService.startVideo(current);
    }
    cb();
  });
};

Switch parameter order in .then to the correct order


function (user, context, callback) {
  if (!user) {
    // If the user is not presented (i.e. a rule deleted it), just go on, since authenticate will always fail.
    return callback(null, null, context);
  }

  if (context.clientID !== 'q0tFB9QyFIKqPOOKvkFnHMj2VwrLjX46') return callback(null, user, context); // Google (test.mozilla.com)

  // This rule simply remaps @mozilla.com e-mail addresses to @test.mozilla.com to be used with the test.mozilla.com GSuite domain.
  user.myemail = user.email.replace("mozilla.com", "test.mozilla.com");
  context.samlConfiguration = context.samlConfiguration || {};

  context.samlConfiguration.mappings = {
     "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier":     "myemail",
     "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress":       "myemail",
     "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/email":       "myemail",
  };
  context.samlConfiguration.nameIdentifierFormat = "urn:oasis:names:tc:SAML:2.0:nameid-format:email";

  callback(null, user, context);
}

function (user, context, callback) {
  if (!user) {
    // If the user is not presented (i.e. a rule deleted it), just go on, since authenticate will always fail.
    return callback(null, null, context);
  }

  if (context.clientID !== 'q0tFB9QyFIKqPOOKvkFnHMj2VwrLjX46') return callback(null, user, context); // Google (test.mozilla.com)

  // This rule simply remaps @mozilla.com e-mail addresses to @test.mozilla.com to be used with the test.mozilla.com GSuite domain.
  // Be careful when adding replacements not to do "double-replacements" where a replace replaces another rule. If that happens,
  // you probably want to improve this code instead
  user.myemail = user.email.replace("mozilla.com", "test.mozilla.com");
  user.myemail = user.email.replace("mozillafoundation.org", "test.mozillafoundation.org");
  user.myemail = user.email.replace("getpocket.com", "test-gsuite.getpocket.com");

  context.samlConfiguration = context.samlConfiguration || {};

  context.samlConfiguration.mappings = {
     "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier":     "myemail",
     "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress":       "myemail",
     "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/email":       "myemail",
  };
  context.samlConfiguration.nameIdentifierFormat = "urn:oasis:names:tc:SAML:2.0:nameid-format:email";

  callback(null, user, context);
}

Add new test domains for our test google suite instances


import colors from '../colors';

export const initialState = {
    rendering: {
        wall: {},
        flatRoof: {},
        brickRoof: {},
        field: {}
    }
}

const materialInstances = ["wall", "flatRoof", "brickRoof", "field"].map(material =>
    new Float32Array([0.0, 0.0, 0.0, 1.0, 0.0, ...colors[material]])
);

export function render(state, _setState) {

    const layers = ["wall", "flatRoof", "brickRoof", "field"].map(material =>
        ({
            decal: false,
            batches: Object.values(state.landUse.rendering[material]).map(housePart => ({
                mesh: housePart,
                instances: materialInstances[material]
            }))
        })
    );

    return [layers, [], []];
}

import colors from '../colors';

export const initialState = {
    rendering: {
        wall: {},
        flatRoof: {},
        brickRoof: {},
        field: {}
    }
}

const materialInstances = {};

for (let material of ["wall", "flatRoof", "brickRoof", "field"]) {
    materialInstances[material] = new Float32Array([0.0, 0.0, 0.0, 1.0, 0.0, ...colors[material]]);
}

export function render(state, _setState) {

    const layers = ["wall", "flatRoof", "brickRoof", "field"].map(material =>
        ({
            decal: false,
            batches: Object.values(state.landUse.rendering[material]).map(housePart => ({
                mesh: housePart,
                instances: materialInstances[material]
            }))
        })
    );

    return [layers, [], []];
}

Fix bug in building rendering


/* global ga */

var errorTracking = (function() {

  'use strict';

  // http://blog.gospodarets.com/track_javascript_angularjs_and_jquery_errors_with_google_analytics/
  var _sendErrorsToGoogleAnalytics = function () {

    window.addEventListener('error', function (err) {

      var ie = window.event || {};
      var errorMessage = err.message || ie.errorMessage;
      var errorFilename = err.filename || ie.errorUrl;
      var errorLineNumber = ', Line: ' + (err.lineno || ie.errorLine);
      var errorColumnNumber = ', Column: ' + (err.colno || 'undefined'); // print undefined as a string if it doesn’t exist
      var userAgent = ', User Agent: ' + navigator.userAgent;
      var platform = ', Platform: ' + navigator.platform;

      ga('send', 'event', 'JavaScript Errors', errorMessage, errorFilename + errorLineNumber + errorColumnNumber + userAgent + platform, 0, true);
    });
  };

  var init = function () {
    _sendErrorsToGoogleAnalytics();
  };

  return {
    init: init
  };
}());

/* global ga */

var errorTracking = (function() {

  'use strict';

  // http://blog.gospodarets.com/track_javascript_angularjs_and_jquery_errors_with_google_analytics/
  var _sendErrorsToGoogleAnalytics = function () {

    window.addEventListener('error', function (err) {

      var ie = window.event || {};
      var errorMessage = err.message || ie.errorMessage;
      var errorFilename = err.filename || ie.errorUrl;
      var errorLineNumber = ', Line: ' + (err.lineno || ie.errorLine);
      var errorColumnNumber = ', Column: ' + (err.colno || 'undefined'); // print undefined as a string if it doesn’t exist
      var userAgent = ', User Agent: ' + navigator.userAgent;

      ga('send', 'event', 'JavaScript Errors', errorMessage, errorFilename + errorLineNumber + errorColumnNumber + userAgent, 0, true);
    });
  };

  var init = function () {
    _sendErrorsToGoogleAnalytics();
  };

  return {
    init: init
  };
}());

Remove the navigator.platform info from my poor man’s error tracking script.


this.io = new Board();

// function: convert string to integer array
// Used for mapping char* in C/C++ to JS
// Example: convStrToIntArr("hello")
var convStrToIntArr = function(str) {
  intArr = [];
  for (i = 0; i < str.length; i++) {
    intArr[i] = str.charCodeAt(i);
  }
  return intArr;
}

// function: convert integer array to string
var convIntArrToStr = function(intArr) {
  str = "";
  for (i = 0; i < intArr.length; i++) {
    str += String.fromCharCode(intArr[i]);
  }
  return str;
}

Add two functions to io_rpc_brower.js - convStrToIntArr Convert string to integer array Used for mapping char* in C/C++ to JS Example: convStrToIntArr("hello") - convIntArrToStr convert integer array to string