import config from '../../config';

function formatUrl(path) {
  const adjustedPath = path[0] !== '/' ? '/' + path : path;
  const apiPath = `/api/${config.apiVersion}${adjustedPath}`;

  return apiPath;
}

class ApiAjax {
  constructor() {
    ['get', 'post', 'put', 'patch', 'del'].forEach((method) =>
      this[method] = (path, { data } = {}) => new Promise((resolve, reject) => {
        const req = new XMLHttpRequest();
        const url = formatUrl(path);

        req.onload = () => {
          if (req.status === 500) {
            reject(req.response);
            return;
          }

          if (req.response.length > 0) {
            resolve(JSON.parse(req.response));
            return;
          }

          resolve(null);
        };

        /**
         * Only covers network errors between the browser and the Express HTTP proxy
         */
        req.onerror = () => {
          reject(null);
        };

        req.open(method, url);
        req.setRequestHeader('Accept', 'application/json');
        req.setRequestHeader('Content-Type', 'application/json');
        req.send(JSON.stringify(data));
      })
    );
  }
}

export default ApiAjax;

import config from '../../config';

function formatUrl(path) {
  const adjustedPath = path[0] !== '/' ? '/' + path : path;
  const apiPath = `/api/${config.apiVersion}${adjustedPath}`;

  return apiPath;
}

class ApiAjax {
  constructor() {
    ['get', 'post', 'put', 'patch', 'del'].forEach((method) =>
      this[method] = (path, { data, header } = {}) => new Promise((resolve, reject) => {
        const req = new XMLHttpRequest();
        const url = formatUrl(path);

        req.onload = () => {
          if (req.status === 500) {
            reject(req.response);
            return;
          }

          if (req.response.length > 0) {
            resolve(JSON.parse(req.response));
            return;
          }

          resolve(null);
        };

        /**
         * Only covers network errors between the browser and the Express HTTP proxy
         */
        req.onerror = () => {
          reject(null);
        };

        req.open(method, url);
        req.setRequestHeader('Accept', 'application/json');
        req.setRequestHeader('Content-Type', 'application/json');
        if (Object.keys(header || {}).length) {
          req.setRequestHeader(header.key, header.value);
        }
        req.send(JSON.stringify(data));
      })
    );
  }
}

export default ApiAjax;

Add custom header for AJAX requests


/**
@module ember
@submodule ember-htmlbars
*/

import Ember from "ember-metal/core";
import { isGlobal } from "ember-metal/path_cache";
import SimpleStream from "ember-metal/streams/simple-stream";

export default function getRoot(scope, key) {
  if (key === 'this') {
    return [scope.self];
  } else if (isGlobal(key) && Ember.lookup[key]) {
    return [getGlobal(key)];
  } else if (scope.locals[key]) {
    return [scope.locals[key]];
  } else {
    return [getKey(scope, key)];
  }
}

function getKey(scope, key) {
  if (key === 'attrs' && scope.attrs) {
    return scope.attrs;
  }

  var self = scope.self || scope.locals.view;

  if (scope.attrs && key in scope.attrs) {
    Ember.deprecate("You accessed the `" + key + "` attribute directly. Please use `attrs." + key + "` instead.");
    return scope.attrs[key];
  } else if (self) {
    return self.getKey(key);
  }
}

var globalStreams = {};

function getGlobal(name) {
  Ember.deprecate("Global lookup of " + name + " from a Handlebars template is deprecated")

  var globalStream = globalStreams[name];

  if (globalStream === undefined) {
    var global = Ember.lookup[name];
    globalStream = new SimpleStream(global, name);
    globalStreams[name] = globalStream;
  }

  return globalStream;
}

/**
@module ember
@submodule ember-htmlbars
*/

import Ember from "ember-metal/core";
import { isGlobal } from "ember-metal/path_cache";
import SimpleStream from "ember-metal/streams/simple-stream";

export default function getRoot(scope, key) {
  if (key === 'this') {
    return [scope.self];
  } else if (isGlobal(key) && Ember.lookup[key]) {
    return [getGlobal(key)];
  } else if (scope.locals[key]) {
    return [scope.locals[key]];
  } else {
    return [getKey(scope, key)];
  }
}

function getKey(scope, key) {
  if (key === 'attrs' && scope.attrs) {
    return scope.attrs;
  }

  var self = scope.self || scope.locals.view;

  if (scope.attrs && key in scope.attrs) {
    Ember.deprecate("You accessed the `" + key + "` attribute directly. Please use `attrs." + key + "` instead.");
    return scope.attrs[key];
  } else if (self) {
    return self.getKey(key);
  }
}

function getGlobal(name) {
  Ember.deprecate("Global lookup of " + name + " from a Handlebars template is deprecated")

  // This stream should be memoized, but this path is deprecated and
  // will be removed soon so it's not worth the trouble.
  return new SimpleStream(Ember.lookup[name], name);
}

Remove global stream memoization to fix more tests


const intialState = [
  { name: 'hotels', query: 'hotel' },
  { name: 'points of interest', query: 'point of interest' },
  { name: 'museums', query: 'museum' },
  { name: 'nightlife', query: 'night club' },
  { name: 'restaurants', query: 'restaurant' },
];

const branchTitles = (state = intialState, action) => {
  switch (action.type) {
    case 'UPDATE_BRANCH_TITLES':
      return Object.assign({}, state, {
        branchTitles: action.payload,
      });
    default:
      return state;
  }
};

export default branchTitles;

const intialState = { default: [
  { name: 'hotels', query: 'hotel' },
  { name: 'points of interest', query: 'point of interest' },
  { name: 'museums', query: 'museum' },
  { name: 'nightlife', query: 'night club' },
  { name: 'restaurants', query: 'restaurant' },
] };

const branchTitles = (state = intialState, action) => {
  switch (action.type) {
    case 'UPDATE_BRANCH_TITLES':
      return Object.assign({}, state, {
        branchTitles: action.payload,
      });
    default:
      return state;
  }
};

export default branchTitles;

Change branchtitle reducer to have default key holding default values.


'use strict'

import MultiTask from 'chiffchaff-multi'
import PipeTask from 'chiffchaff-pipe'
import defaults from 'defaults'
import EventRegistry from 'event-registry'

const toTaskIterator = (sources, destination) => (function * () {
  for (const source of sources) {
    yield new PipeTask(source, destination, {end: false})
  }
})()

export default class ConcatTask extends MultiTask {
  constructor (sources = null, destination = null, options = null) {
    super(null, defaults(options, {ignoreWeights: true, size: 0}))
    this._sources = sources
    this._destination = destination
  }

  get destination () {
    return this._destination
  }

  set destination (value) {
    this._destination = value
  }

  get size () {
    return super.size
  }

  set size (value) {
    this.options.size = value
  }

  _start () {
    this._tasks = toTaskIterator(this._sources, this._destination)
    return super._start()
      .then(() => this._awaitFinish())
  }

  _awaitFinish () {
    return new Promise((resolve, reject) => {
      const reg = new EventRegistry()
      reg.onceFin(this._destination, 'finish', resolve)
      reg.onceFin(this._destination, 'error', reject)
      this._destination.end()
    })
  }
}

'use strict'

import MultiTask from 'chiffchaff-multi'
import PipeTask from 'chiffchaff-pipe'
import defaults from 'defaults'
import EventRegistry from 'event-registry'

const toTaskIterator = (sources, destination) => (function * () {
  for (const source of sources) {
    yield new PipeTask(source, destination, {end: false})
  }
})()

export default class ConcatTask extends MultiTask {
  constructor (sources = null, destination = null, options = null) {
    super(null, defaults(options, {ignoreWeights: true, size: 0}))
    this._sources = sources
    this._destination = destination
  }

  get destination () {
    return this._destination
  }

  set destination (value) {
    this._destination = value
  }

  get size () {
    return super.size
  }

  set size (value) {
    this.options.size = value
  }

  _start () {
    const ending = new Promise((resolve, reject) => {
      const reg = new EventRegistry()
      reg.onceFin(this._destination, 'finish', resolve)
      reg.onceFin(this._destination, 'error', reject)
    })
    this._tasks = toTaskIterator(this._sources, this._destination)
    return super._start()
      .then(() => this._destination.end())
      .then(() => ending)
  }
}

Add completion listeners earlier so we don't miss sync calls


/* globals MarkdownFilePaths: false */
// MarkdownFilePaths are created in run.js and passed through webpack

import React from 'react';
import { Route, IndexRoute } from 'react-router';
import Landing from './pages/home/index';
import Guide from './pages/guide/index';
import GuideList from './pages/guideList/index';
import NotFound from './pages/error/index';
import ComingSoon from './pages/comingSoon';

// does not work when passing './content' as an variable
const req = require.context('./content', true, /^\.\/.*\.md/);

const routesForMarkdownFiles = MarkdownFilePaths.map(path => {
  const { title, html } = req(`./${path}`);
  const url = `${path.slice(0, -'.md'.length)}/`;
  console.log(`[Route generator] file ${path} -> url ${url}`);
  return <Route key={path} path={url} title={title} docHtml={html} />;
});

const routes = (
  <Route path="/">
    <IndexRoute title="Skygear Documentation" component={Landing} />
    <Route path="guides/" component={GuideList} />
    <Route path="guide" component={Guide}>
      {routesForMarkdownFiles}
    </Route>
    <Route path="coming-soon/" title="Coming Soon" component={ComingSoon} />
    <Route path="*" title="404: Not Found" component={NotFound} />
  </Route>
);

// Be sure to export the React component so that it can be statically rendered
export default routes;

/* globals MarkdownFilePaths: false */
// MarkdownFilePaths are created in run.js and passed through webpack

import React from 'react';
import { Route, IndexRoute } from 'react-router';
import Landing from './pages/home/index';
import Guide from './pages/guide/index';
import GuideList from './pages/guideList/index';
import NotFound from './pages/error/index';
import ComingSoon from './pages/comingSoon';

// does not work when passing './content' as an variable
const req = require.context('./content', true, /^\.\/.*\.md/);

const routesForMarkdownFiles = MarkdownFilePaths.map(path => {
  const { title, html } = req(`./${path}`);
  const url = `${path.slice(0, -'.md'.length)}/`;
  console.log(`[Route generator] file ${path} -> url ${url}`);
  return <Route key={path} path={url} title={title} docHtml={html} />;
});

const routes = (
  <Route path="/">
    <IndexRoute title="Skygear Documentation" component={Landing} />
    <Route path="guides/" title="Guides" component={GuideList} />
    <Route path="guide" component={Guide}>
      {routesForMarkdownFiles}
    </Route>
    <Route path="coming-soon/" title="Coming Soon" component={ComingSoon} />
    <Route path="*" title="404: Not Found" component={NotFound} />
  </Route>
);

// Be sure to export the React component so that it can be statically rendered
export default routes;

Add html title to guide list


elation.require([], function() {
  elation.component.add('janusweb.translators.blank', function() {
    this.exec = function(args) {
      return new Promise(function(resolve, reject) {
        var roomdata = {
          room: {
            use_local_asset: 'room_plane',
            pos: [0, 0, 0],
            orientation: new THREE.Quaternion().setFromEuler(new THREE.Euler(0,0,0))
          },
          object: [],
          link: []
        };
        //var bookmarks = elation.collection.localindexed({key: 'janusweb.bookmarks'});
        resolve(roomdata);
      });
    }
  });
});

elation.require([], function() {
  elation.component.add('janusweb.translators.blank', function() {
    this.exec = function(args) {
      return new Promise(function(resolve, reject) {
        var roomdata = {
          room: {
            use_local_asset: 'room_plane',
            pos: [0, 0, 0],
            orientation: new THREE.Quaternion().setFromEuler(new THREE.Euler(0,0,0)),
            skybox_left_id: 'black',
            skybox_right_id: 'black',
            skybox_back_id: 'black',
            skybox_front_id: 'black',
            skybox_up_id: 'black',
            skybox_down_id: 'black',
          },
          object: [],
          link: []
        };
        //var bookmarks = elation.collection.localindexed({key: 'janusweb.bookmarks'});
        resolve(roomdata);
      });
    }
  });
});

Use black skybox for default web translator


/**
 * util/core.spec.js
 *
 * @author  Rock Hu <rockia@mac.com>
 * @license MIT
 */
 import Endpoints    from '../../src/config/endpoints.json';
 import API          from '../../src/config/api.json';

var Sinon           = require('sinon');
var Chai            = require('chai');
var Path            = require('path');

Chai.use(require('sinon-chai'));
Chai.should();

var expect         = Chai.expect;
var index      = require('../../src/index.js');

describe('index', function() {
  var options = {
    api_key: '1234',
    platform: 'production',
    region: 'NA'
  };
  class APIDriver{};
  var apidriverObj      = new APIDriver(Endpoints,API,options);

  it('should return APIDriver Object', function(){
    expect(apidriverObj).to.be.an.instanceof(APIDriver);
  });
});

/**
 * util/core.spec.js
 *
 * @author  Rock Hu <rockia@mac.com>
 * @license MIT
 */
 import Endpoints    from '../../src/config/endpoints.json';
 import API          from '../../src/config/api.json';

var Sinon           = require('sinon');
var Chai            = require('chai');
var Path            = require('path');

Chai.use(require('sinon-chai'));
Chai.should();

var expect         = Chai.expect;
var index      = require('../../src/index.js');

describe('index', function() {
    it('should return APIDriver Object', function(){
        var options = {
            api_key: '1234',
            platform: 'production',
            region: 'NA'
        };
        class APIDriver{};
        var apidriverObj      = new APIDriver(Endpoints,API,options);
        expect(apidriverObj).to.be.an.instanceof(APIDriver);
    });

});

Update index test case 1


Meteor.publish('allPosts', function () {
  "use strict";
  var result = Posts.find({}, {
    limit: 50,
    fields: {
      oldChildren: false
    }
  });
  return result;
});

Meteor.publish('comments', function (id) {
  "use strict";

  return Posts.find({
    _id: id
  });
});

Meteor.publish('user', function (username) {
  "use strict";

  console.log(Posts.find().fetch())
  return Posts.find({
    author: username
  },{
    limit: 50,
    fields: {
      oldChildren: false
    }
  });
});

Meteor.publish('recentPosts', function () {
  "use strict";
  return Posts.find({}, {
    sort: {
      createdAt: -1
    },
    limit: 50,
    fields: {
      oldChildren: false
    }
  });
});

Meteor.publish('topPosts', function (start) {
  "use strict";
  return Posts.find({
    oldPoints: {
      $gt: 1
    },
    createdAt: {
      $gte: start
    }
  }, {
    sort: {
      oldPoints: -1
    },
    limit: 50,
    fields: {
      oldChildren: false
    }
  });
});

Meteor.publish('hotPosts', function () {
  "use strict";
  return Posts.find({}, {
    limit: 50,
    sort: {
      heat: -1
    },
    fields: {
      oldChildren: false
    }
  });
});

Meteor.publish('allPosts', function () {
  "use strict";
  var result = Posts.find({}, {
    limit: 50,
    fields: {
      oldChildren: false
    }
  });
  return result;
});

Meteor.publish('comments', function (id) {
  "use strict";

  return Posts.find({
    _id: id
  });
});

Meteor.publish('user', function (username) {
  "use strict";

  return Posts.find({
    author: username
  },{
    limit: 50,
    fields: {
      oldChildren: false
    }
  });
});

Meteor.publish('recentPosts', function () {
  "use strict";
  return Posts.find({}, {
    sort: {
      createdAt: -1
    },
    limit: 50,
    fields: {
      oldChildren: false
    }
  });
});

Meteor.publish('topPosts', function (start) {
  "use strict";
  return Posts.find({
    oldPoints: {
      $gt: 1
    },
    createdAt: {
      $gte: start
    }
  }, {
    sort: {
      oldPoints: -1
    },
    limit: 50,
    fields: {
      oldChildren: false
    }
  });
});

Meteor.publish('hotPosts', function () {
  "use strict";
  return Posts.find({}, {
    limit: 50,
    sort: {
      heat: -1
    },
    fields: {
      oldChildren: false
    }
  });
});

Remove the console.log from the user pub


exports.TOKEN = ‘TOKEN HERE’;
exports.SESSION_SECRET = ‘SESSION SECRET HERE’;
exports.CLIENT_ID = ‘CLIENT ID HERE’;
exports.CLIENT_SECRET = ‘CLIENT SECRET HERE’;

exports.TOKEN = 'TOKEN HERE';
exports.SESSION_SECRET = 'SESSION SECRET HERE';
exports.CLIENT_ID = 'CLIENT ID HERE';
exports.CLIENT_SECRET = 'CLIENT SECRET HERE';

Remove fancy quotations, thanks Gmail


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

export function selectKey(id) {
  return { type: types.SELECT_KEY, id }
}

export function toggleCompose() {
  return { type: types.TOGGLE_COMPOSE }
}

export function showComposeWithType(type) {
  return { type: types.SHOW_COMPOSE_WITH_TYPE, data: type }
}

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

export function selectKey(id) {
  return { type: types.SELECT_KEY, id }
}

export function toggleCompose() {
  return { type: types.TOGGLE_COMPOSE }
}

export function showComposeWithType(type) {
  return { type: types.SHOW_COMPOSE_WITH_TYPE, data: type }
}

Use new constant file name


define("game-manager", ["game"], function(Game) {
    function GameManager() {
        this.games = this.load() || [];
        this.next_id = this.getNextId();
    }

    GameManager.prototype = {
        addGame: function() {
            var game = new Game(this.next_id++);
            this.games.push(game);
            this.save();
            return game;
        },
        deleteGame: function(game) {
            var index = this.games.indexOf(game);
            if (index == -1)
                throw new Error("Bad game");
            this.games.splice(index, 1);
        },
        findGame: function(id) {
            for (var i = 0; i < this.games.length; i++)
                if (this.games[i].id == id)
                    return this.games[i];
        },
        listGames: function() {
            return this.games;
        },
        getNextId: function() {
            var next = 1;
            this.games.forEach(function(g) {
                next = Math.max(next, g.id + 1);
            });
            return next;
        },
        load: function() {
            return (JSON.parse(localStorage.getItem('games')) || []).map(function(game) {
                return new Game(game.id, game);
            });
        },
        save: function() {
            localStorage.setItem('games', JSON.stringify(this.games));
        },
    };

    return GameManager;
});

define("game-manager", ["game"], function(Game) {
    function GameManager() {
        this.games = this.load() || [];
        this.next_id = this.getNextId();
    }

    GameManager.prototype = {
        addGame: function() {
            var game = new Game(this.next_id++);
            this.games.push(game);
            this.save();
            return game;
        },
        deleteGame: function(game) {
            var index = this.games.indexOf(game);
            if (index == -1)
                throw new Error("Bad game");
            this.games.splice(index, 1);
        },
        findGame: function(id) {
            for (var i = 0; i < this.games.length; i++)
                if (this.games[i].id == id)
                    return this.games[i];
        },
        listGames: function() {
            return this.games;
        },
        getNextId: function() {
            var next = 1;
            this.games.forEach(function(g) {
                next = Math.max(next, g.id + 1);
            });
            return next;
        },
        load: function() {
            return (JSON.parse(localStorage.getItem('games')) || []).map(function(game) {
                return new Game(game.id, game);
            });
        },
        save: function() {
            // remove "deleted": false fields from all logs (unnecessary)
            this.games.map(function(game) {
                game.log.map(function(e) {
                    if (!e.deleted)
                        e.deleted = undefined;
                });
            });
            localStorage.setItem('games', JSON.stringify(this.games));
        },
    };

    return GameManager;
});

Save a bit of space when saving logs


// Generated by CoffeeScript 1.6.3
(function() {
  var clicks, io, tones;

  io = require('socket.io').listen(process.env.PORT || 8888);

  clicks = [];

  tones = io.of('/tones').on('connection', function(socket) {
    socket.on('greeting', function(data) {
      console.log(data);
      return socket.emit('greeting', {
        greeting: 'Hello client!'
      });
    });
    socket.emit('grid status', {
      clicks: clicks
    });
    return socket.on('grid click', function(data) {
      console.log(data);
      clicks.push(data);
      return socket.broadcast.emit('grid click', {
        element: data.element,
        sender: data.sender
      });
    });
  });

}).call(this);

// Generated by CoffeeScript 1.6.3
(function() {
  var clicks, io, tones;

  var app = require('http').createServer(function() {});
  io = require('socket.io').listen(app);

  clicks = [];

  tones = io.of('/tones').on('connection', function(socket) {
    socket.on('greeting', function(data) {
      console.log(data);
      return socket.emit('greeting', {
        greeting: 'Hello client!'
      });
    });
    socket.emit('grid status', {
      clicks: clicks
    });
    return socket.on('grid click', function(data) {
      console.log(data);
      clicks.push(data);
      return socket.broadcast.emit('grid click', {
        element: data.element,
        sender: data.sender
      });
    });
  });

  app.listen(process.env.PORT || 8888);

}).call(this);

Fix problem with startup on heroku


'use strict'

import { Schema } from 'mongoose'

import { connectionAPI, connectionDefault } from '../config'

const ClientSchema = new Schema({
  clientID: {
    type: String, required: true, unique: true, index: true
  },
  clientDomain: {
    type: String, index: true
  },
  name: {
    type: String, required: true
  },
  roles: [{type: String, required: true}],
  passwordAlgorithm: String,
  passwordHash: String,
  passwordSalt: String,
  certFingerprint: String,
  organization: String,
  location: String,
  softwareName: String,
  description: String,
  contactPerson: String,
  contactPersonEmail: String
})

// compile the Client Schema into a Model
export const ClientModelAPI = connectionAPI.model('Client', ClientSchema)
export const ClientModel = connectionDefault.model('Client', ClientSchema)

'use strict'

import { Schema } from 'mongoose'

import { connectionAPI, connectionDefault } from '../config'

const ClientSchema = new Schema({
  clientID: {
    type: String,
    required: true,
    unique: true,
    index: true
  },
  clientDomain: {
    type: String,
    index: true
  },
  name: {
    type: String,
    required: true
  },
  roles: [{ type: String, required: true }],
  passwordAlgorithm: String,
  passwordHash: String,
  passwordSalt: String,
  certFingerprint: String,
  organization: String,
  location: String,
  softwareName: String,
  description: String,
  contactPerson: String,
  contactPersonEmail: String
})

export const ClientModelAPI = connectionAPI.model('Client', ClientSchema)
export const ClientModel = connectionDefault.model('Client', ClientSchema)

Format the client model schema


/* global wp, _, kirki */
wp.customize.controlConstructor['kirki-repeater'] = wp.customize.kirkiDynamicControl.extend( {
	initKirkiControl: function() {
		var control     = this,
		    rowDefaults = {};

		_.each( control.params.fields, function( field, key ) {
			rowDefaults[ key ] = ( ! _.isUndefined( field['default'] ) ) ? field['default'] : '';
		} );

		control.container.html( kirki.template.repeaterControl( control ) );

		control.container.find( '.add-row' ).click( function() {
			jQuery( control.container.find( '.repeater-fields' ) )
				.append( kirki.template.repeaterControlRow( control, rowDefaults ) );
		});
	}
} );

/* global wp, _, kirki */
wp.customize.controlConstructor['kirki-repeater'] = wp.customize.kirkiDynamicControl.extend( {
	initKirkiControl: function() {
		var control     = this;

		control.container.html( kirki.template.repeaterControl( control ) );

		control.repeaterRowAddButton();
		control.repeaterRowRemoveButton();

	},

	/**
	 * Actions to run when clicking on the "add row" button.
	 */
	repeaterRowAddButton: function() {
		var control = this,
		    rowDefaults = {};

		_.each( control.params.fields, function( field, key ) {
			rowDefaults[ key ] = ( ! _.isUndefined( field['default'] ) ) ? field['default'] : '';
		} );

		control.container.find( '.add-row' ).click( function() {
			jQuery( control.container.find( '.repeater-fields' ) )
				.append( kirki.template.repeaterControlRow( control, rowDefaults ) );
		});
	},

	/**
	 * Actions to run when clicking on the "remove row" button.
	 */
	repeaterRowRemoveButton: function() {
		var control = this;

		control.container.find( '.repeater-row-remove-button' ).click( function( e ) {
			jQuery( this ).parents( '.row-template' ).remove();
		});
	}
} );

Add row & remove row primers


let PROTO_PATH = __dirname + "/wkrpt401.proto"

let grpc = require('grpc');
let proto = grpc.load(PROTO_PATH).wkrpt401;

function getBestPersonality(call, callback) {
  let userData = call.request;
  let name = userData.name;
  let level = userData.level;

  var maxPersonalityName = "";
  var maxPersonalityValue = -1;
  for (var i in userData.personality) {
    let personalityName = userData.personality[i].name;
    let personalityValue = userData.personality[i].amount;
    if (personalityValue > maxPersonalityValue) {
      maxPersonalityName = personalityName;
      maxPersonalityValue = personalityValue;
    }
  }

  let response = "The best personality attribute for " + name
                    + " (Lv. " + level + ") is "
                    + maxPersonalityName + " @ "
                    + maxPersonalityValue;
  console.log("getBestPersonality called with response '" + response + "'");
  callback(null, {response: response});
}

function main() {
  var server = new grpc.Server();
  server.addProtoService(proto.UserManager.service, {getBestPersonality: getBestPersonality});
  server.bind("localhost:50051", grpc.ServerCredentials.createInsecure());

  server.start();
  console.log("WKRPT401 gRPC server starting.");
}

main();

let PROTO_PATH = __dirname + "/wkrpt401.proto"

let grpc = require('grpc');
let proto = grpc.load(PROTO_PATH).wkrpt401;

var requestCount = 0

function getBestPersonality(call, callback) {
  let userData = call.request;
  let name = userData.name;
  let level = userData.level;

  var maxPersonalityName = "";
  var maxPersonalityValue = -1;
  for (var i in userData.personality) {
    let personalityName = userData.personality[i].name;
    let personalityValue = userData.personality[i].amount;
    if (personalityValue > maxPersonalityValue) {
      maxPersonalityName = personalityName;
      maxPersonalityValue = personalityValue;
    }
  }

  let response = "The best personality attribute for " + name
                    + " (Lv. " + level + ") is "
                    + maxPersonalityName + " @ "
                    + maxPersonalityValue;
  requestCount++
  console.log("getBestPersonality called with response '" + response + "'" + " (request #" + requestCount + ")");
  callback(null, {response: response});
}

function main() {
  var server = new grpc.Server();
  server.addProtoService(proto.UserManager.service, {getBestPersonality: getBestPersonality});
  server.bind("localhost:50051", grpc.ServerCredentials.createInsecure());

  server.start();
  console.log("WKRPT401 gRPC server starting.");
}

main();

Add request counter to logging


var example   = require("washington")
var assert    = require("assert")

example("Async: by default")

example("Endpoint: match with glob style wildcards")

example("Repeater: Repeat events back and forth on repeater venue")

example("Repeater: Scope out prefix when sending to repeater")

example("Repeater: Add prefix when receiving from repeater")

example("Configuration: disable async per call")

example("Configuration: disable async per venue")

example("Configuration: set event clone to shallow per call")

example("Configuration: set event clone to disabled per call")

example("Configuration: set event clone to shallow per venue")

example("Configuration: set event clone to disabled per venue")

console.log("Notes: add Mediador as static dependency (Bower instead of NPM)")

console.log("Notes: develop Sidney on src/ dir, expose build on root")

console.log("Notes: use tasks for static building of sidney")

Add configuration requirements and building notes


module('bulk_docs', {
  setup : function () {
    this.name = 'test' + genDBName();
  }
});

asyncTest('Testing bulk docs', function() {
  pouch.open(this.name, function(err, db) {
    var docs = makeDocs(5);
    db.bulkDocs({docs: docs}, function(err, results) {
      ok(results.length === 5, 'results length matches');
      for (var i = 0; i < 5; i++) {
        ok(results[i].id === docs[i]._id, 'id matches');
        ok(results[i].rev, 'rev is set');
        // Update the doc
        docs[i]._rev = results[i].rev;
        docs[i].string = docs[i].string + ".00";
      }
      db.bulkDocs({docs: docs}, function(err, results) {
        ok(results.length === 5, 'results length matches');
        for (i = 0; i < 5; i++) {
          ok(results[i].id == i.toString(), 'id matches again');
          // set the delete flag to delete the docs in the next step
          docs[i]._deleted = true;
        }
        start();
      });
    });
  });
});

module('bulk_docs', {
  setup : function () {
    this.name = 'test' + genDBName();
  }
});

asyncTest('Testing bulk docs', function() {
  pouch.open(this.name, function(err, db) {
    var docs = makeDocs(5);
    db.bulkDocs({docs: docs}, function(err, results) {
      ok(results.length === 5, 'results length matches');
      for (var i = 0; i < 5; i++) {
        ok(results[i].id === docs[i]._id, 'id matches');
        ok(results[i].rev, 'rev is set');
        // Update the doc
        docs[i]._rev = results[i].rev;
        docs[i].string = docs[i].string + ".00";
      }
      db.bulkDocs({docs: docs}, function(err, results) {
        ok(results.length === 5, 'results length matches');
        for (i = 0; i < 5; i++) {
          ok(results[i].id == i.toString(), 'id matches again');
          // set the delete flag to delete the docs in the next step
          docs[i]._rev = results[i].rev;
          docs[i]._deleted = true;
        }
        db.put(docs[0], function(err, doc) {
          db.bulkDocs({docs: docs}, function(err, results) {
            ok(results[0].error === 'conflict', 'First doc should be in conflict');
            ok(typeof results[0].rev === "undefined", 'no rev in conflict');
            for (i = 1; i < 5; i++) {
              ok(results[i].id == i.toString());
              ok(results[i].rev);
            }
            start();
          });
        });
      });
    });
  });
});

Add to bulk docs testing


var zlib = require('zlib');
var inherits = require('util').inherits;

var util = require('./');

function DeflateRawChecksum(options) {
  zlib.DeflateRaw.call(this, options);

  this.checksum = util.crc32.createCRC32();
  this.digest = null;

  this.rawSize = 0;
  this.compressedSize = 0;

  this.on('data', function(chunk) {
    this.compressedSize += chunk.length;
  });

  this.on('end', function() {
    this.digest = this.checksum.digest();
  });
}

inherits(DeflateRawChecksum, zlib.DeflateRaw);

DeflateRawChecksum.prototype._transform = function(chunk, encoding, callback) {
  if (chunk) {
    this.checksum.update(chunk);
    this.rawSize += chunk.length;
  }

  return zlib.DeflateRaw.prototype._transform.call(this, chunk, encoding, callback);
};

module.exports = DeflateRawChecksum;

var zlib = require('zlib');
var inherits = require('util').inherits;

var util = require('./');

function DeflateRawChecksum(options) {
  zlib.DeflateRaw.call(this, options);

  this.checksum = util.crc32.createCRC32();
  this.digest = null;

  this.rawSize = 0;
  this.compressedSize = 0;

  this.on('data', function(chunk) {
    this.compressedSize += chunk.length;
  });

  this.on('end', function() {
    this.digest = this.checksum.digest();
  });
}

inherits(DeflateRawChecksum, zlib.DeflateRaw);

DeflateRawChecksum.prototype.write = function(chunk, cb) {
  if (chunk) {
    this.checksum.update(chunk);
    this.rawSize += chunk.length;
  }

  return zlib.DeflateRaw.prototype.write.call(this, chunk, cb);
};

module.exports = DeflateRawChecksum;

Revert "util: make DeflateRaw Checksum hook into _transform so that it mimicks the norms."


/*! Parker v0.0.0 - MIT license */

'use strict';

var _ = require('underscore');

function CssRule(raw) {
    this.raw = raw;
}

CssRule.prototype.getSelectors = function () {
    return getSelectors(getSelectorBlock(this.raw));
};

CssRule.prototype.getDeclarations = function () {
    return getDeclarations(getDeclarationBlock(this.raw));
};

var getSelectorBlock = function (rule) {
    var pattern = /([\w,\.#\-\[\]\"=\s:>]+)[\s]?\{/g,
        results = pattern.exec(rule);

    return results[1];
};

var getSelectors = function (selectorBlock) {
    var untrimmedSelectors = selectorBlock.split(','),
        trimmedSelectors = untrimmedSelectors.map(function (untrimmed) {
            return untrimmed.trim();
        });

    return trimmedSelectors;
};

var getDeclarationBlock = function (rule) {
    var pattern = /\{(.+)\}/g;

    return pattern.exec(rule)[1];
};

var getDeclarations = function (declarationBlock) {
    var untrimmedDeclarations = _.compact(declarationBlock.trim().split(';')),
        trimmedDeclarations = untrimmedDeclarations.map(function (untrimmed) {
            return untrimmed.trim();
        });

    return trimmedDeclarations;
};

module.exports = CssRule;

/*! Parker v0.0.0 - MIT license */

'use strict';

var _ = require('underscore');

function CssRule(raw) {
    this.raw = raw;
}

CssRule.prototype.getSelectors = function () {
    return getSelectors(getSelectorBlock(this.raw));
};

CssRule.prototype.getDeclarations = function () {
    return getDeclarations(getDeclarationBlock(this.raw));
};

var getSelectorBlock = function (rule) {
    var pattern = /([\w,\.#\-\[\]\"=\s:>\*\(\)]+)[\s]?\{/g,
        results = pattern.exec(rule);

    return results[1];
};

var getSelectors = function (selectorBlock) {
    var untrimmedSelectors = selectorBlock.split(','),
        trimmedSelectors = untrimmedSelectors.map(function (untrimmed) {
            return untrimmed.trim();
        });

    return trimmedSelectors;
};

var getDeclarationBlock = function (rule) {
    var pattern = /\{(.+)\}/g;

    return pattern.exec(rule)[1];
};

var getDeclarations = function (declarationBlock) {
    var untrimmedDeclarations = _.compact(declarationBlock.trim().split(';')),
        trimmedDeclarations = untrimmedDeclarations.map(function (untrimmed) {
            return untrimmed.trim();
        });

    return trimmedDeclarations;
};

module.exports = CssRule;

Fix for universal identifier and not identifier not being recognised


$(document).ready(function() {

    var addItem = function() {
      $('.mainList').append('
<input id="check" class="checkBox" type="checkbox"><input class="textInp" type="text" placeholder="...">
');
    };

    var itemDone = function() {
        if ($(this).is(':checked')) {
            alert("Checked!");
        } else {
            alert("Unchecked!");
        }
    };

    $('.mainList').on('click', '#check', itemDone);
    $('.addItem').click(addItem);
});

$(document).ready(function() {

    var addItem = function() {
      $('.mainList').append('
<input id="check" class="checkBox" type="checkbox"><input class="textInp" type="text" placeholder="Add Item...">
');
    };

    var itemDone = function() {
        var $this = $(this);
        $this.parent().fadeOut(600, function() {
            $this.parent().remove();
        });
    };

    $('.mainList').on('click', '#check', itemDone);
    $('.addItem').click(addItem);
});

Make list items fade out on check.


'use strict';
var co6 = require('co6');
var fs = co6.promisifyAll(require('fs'));
var os = require('os');
var parse = require('./parse');
var server = require('../server');

/*
 * Run the command line application.
 */
co6.main(function *() {
    var options = parse(process.argv);
    var source = options.source || 'MangaRack.txt';
    var tasks = options.args.length ? args(options) : yield batch(source);
    yield server(tasks, options.workers || os.cpus().length, console.log);
    console.log('Completed!');
});

/**
 * Process the arguments.
 * @param {!Options} options
 * @return {!Array.<!{address: string, !Options}>}
 */
function args(options) {
    var tasks = [];
    options.args.forEach(function (address) {
        tasks.push({address: address, options: options});
    });
    console.log('meh');
    return tasks;
}

/**
 * Process the batch file.
 * @param {string} filePath
 * @return {!Array.<!{address: string, !Options}>}
 */
function *batch(filePath) {
    var tasks = [];
    if (!(yield fs.existsAsync(filePath))) return tasks;
    yield fs.readFileAsync(filePath, 'utf8').split('\n').forEach(function (n) {
        var lineOptions = parse(n.split(' '));
        lineOptions.args.forEach(function (address) {
            tasks.push({address: address, options: lineOptions});
        });
    });
    return tasks;
}

'use strict';
var co6 = require('co6');
var fs = co6.promisifyAll(require('fs'));
var os = require('os');
var parse = require('./parse');
var server = require('../server');

/*
 * Run the command line application.
 */
co6.main(function *() {
    var options = parse(process.argv);
    var source = options.source || 'MangaRack.txt';
    var tasks = options.args.length ? args(options) : yield batch(source);
    yield server(tasks, options.workers || os.cpus().length, console.log);
    console.log('Completed!');
});

/**
 * Process the arguments.
 * @param {!Options} options
 * @return {!Array.<!{address: string, !Options}>}
 */
function args(options) {
    var tasks = [];
    options.args.forEach(function (address) {
        tasks.push({address: address, options: options});
    });
    console.log('meh');
    return tasks;
}

/**
 * Process the batch file.
 * @param {string} path
 * @return {!Array.<!{address: string, !Options}>}
 */
function *batch(path) {
    var tasks = [];
    if (!(yield fs.existsAsync(path))) return tasks;
    (yield fs.readFileAsync(path, 'utf8')).split('\n').forEach(function (n) {
        var lineOptions = parse(n.split(' '));
        lineOptions.args.forEach(function (address) {
            tasks.push({address: address, options: lineOptions});
        });
    });
    return tasks;
}

Fix the cli batch processing yield


//= require ./select_button_view
//= require ./text_field_view

Flame.ComboBoxView = Flame.SelectButtonView.extend({
    classNames: ['flame-combo-box-view'],
    childViews: 'textView buttonView'.w(),
    handlebars: undefined,
    acceptsKeyResponder: false,

    textView: Flame.TextFieldView.extend({
        layout: { left: 0, right: 0 },
        valueBinding: 'parentView.value'
    }),

    insertSpace: function() { return false; },

    buttonView: Flame.ButtonView.extend({
        acceptsKeyResponder: false,
        handlebars: '<img src="%@">'.fmt(Flame.image('select_button_arrow.png')),
        layout: { right: -5, width: 22, height: 22 },

        action: function() {
            this.get('parentView')._openMenu();
        }
    })
});

//= require ./select_button_view
//= require ./text_field_view

Flame.ComboBoxView = Flame.SelectButtonView.extend({
    classNames: ['flame-combo-box-view'],
    childViews: 'textView buttonView'.w(),
    handlebars: undefined,
    acceptsKeyResponder: false,

    textView: Flame.TextFieldView.extend({
        layout: { left: 0, right: 3 },
        valueBinding: 'parentView.value'
    }),

    insertSpace: function() { return false; },

    buttonView: Flame.ButtonView.extend({
        acceptsKeyResponder: false,
        handlebars: '<img src="%@">'.fmt(Flame.image('select_button_arrow.png')),
        layout: { right: -2, width: 22, height: 22 },

        action: function() {
            this.get('parentView')._openMenu();
        }
    })
});

Fix Combo box margin issue


import { hierarchy } from 'd3-hierarchy';

export default class Clusters {
  constructor () {
    this.data = {
      children: [
        {
          cluster: 'non-anomalous',
          value: 0
        },
        {
          cluster: 'anomalous',
          value: 0,
          children: []
        }
      ]
    };
  }

  add () {
    this.data.children[0].value++;
  }

  remove () {
    this.data.children[0].value--;
  }

  addAnomalous (cluster) {
    this.ensureCluster(cluster);
    this.data.children[1].children[cluster].value++;
  }

  removeAnomalous (cluster) {
    this.data.children[1].children[cluster].value--;
  }

  ensureCluster (cluster) {
    if (this.data.children[1].children.length <= cluster) {
      for (let i = this.data.children[1].children.length; i < cluster + 1; i++) {
        this.data.children[1].children[i] = {
          cluster: i,
          value: 0
        };
      }
    }
  }

  hierarchy () {
    return hierarchy(this.data)
      .sum(d => d.value || 0.1);
  }

  count () {
    return this.data.children[0].value;
  }

  anomalousCounts () {
    return this.data.children[1].children
      .sort((a, b) => a.cluster - b.cluster)
      .map(d => d.value);
  }
}

import { hierarchy } from 'd3-hierarchy';

export default class Clusters {
  constructor () {
    this.data = {
      children: [
        {
          cluster: 'non-anomalous',
          value: 0
        },
        {
          cluster: 'anomalous',
          value: 0,
          children: []
        }
      ]
    };
  }

  add () {
    this.data.children[0].value++;
  }

  remove () {
    this.data.children[0].value--;
  }

  addAnomalous (cluster) {
    this.ensureCluster(cluster);
    this.data.children[1].children[cluster].value++;
  }

  removeAnomalous (cluster) {
    this.data.children[1].children[cluster].value--;
  }

  ensureCluster (cluster) {
    if (this.data.children[1].children.length <= cluster) {
      for (let i = this.data.children[1].children.length; i < cluster + 1; i++) {
        this.data.children[1].children[i] = {
          cluster: i,
          value: 0
        };
      }
    }
  }

  hierarchy () {
    return hierarchy(this.data)
      .sum(d => d.value || 0.01);
  }

  count () {
    return this.data.children[0].value;
  }

  anomalousCounts () {
    return this.data.children[1].children
      .sort((a, b) => a.cluster - b.cluster)
      .map(d => d.value);
  }
}

Make zero-element bubbles a bit smaller


module.exports = function (sequelize, DataTypes) {
  const Rating = sequelize.define('Rating', {
    id: {
      primaryKey: true,
      type: DataTypes.UUID,
      defaultValue: DataTypes.UUIDV4
    },
    value: {
      type: DataTypes.INTEGER,
      allowNull: false,
      validate: {
        min: 0
      }
    },
    BikeId: {
      type: DataTypes.UUID,
      allowNull: false
    },
    VoteId: {
      type: DataTypes.UUID,
      allowNull: false
    }
  }, {
    classMethods: {
      associate: function associate (models) {
        Rating.belongsTo(models.Bike)
        Rating.belongsTo(models.Vote)
      }
    }
  })

  return Rating
}

module.exports = function (sequelize, DataTypes) {
  const Rating = sequelize.define('Rating', {
    id: {
      primaryKey: true,
      type: DataTypes.UUID,
      defaultValue: DataTypes.UUIDV4
    },
    value: {
      type: DataTypes.INTEGER,
      allowNull: false,
      validate: {
        min: 0
      }
    },
    BikeId: {
      type: DataTypes.UUID,
      allowNull: false
    },
    VoteId: {
      type: DataTypes.UUID,
      allowNull: false
    }
  }, {
    classMethods: {
      associate (models) {
        Rating.belongsTo(models.Bike)
        Rating.belongsTo(models.Vote)
      }
    }
  })

  return Rating
}

Use es6 style object function


'use-strict';

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

module.exports = {
  context: __dirname,

  entry: {
    app: [
      'webpack-hot-middleware/client',
      'babel-polyfill',
      './js/index'
    ],
    style: './css/index.scss'
  },

  output: {
    path: path.join(__dirname, 'assets', 'js'),
    filename: '[name].bundle.js',
    publicPath: '/assets/js/'
  },

  module: {
    preLoaders: [{
      loader: 'eslint',
      test: /\.jsx?$/,
      exclude: /node_modules/
    }],
    loaders: [{
      loader: 'babel',
      test: /\.jsx?$/,
      exclude: /node_modules/
    }, {
      loaders: ['style', 'css?sourceMap', 'sass?sourceMap'],
      test: /\.scss$/
    }]
  },

  resolve: {
    extensions: ['', '.js', '.jsx'],
    modulesDirectories: ['node_modules']
  },

  debug: true,

  devtool: 'eval',

  plugins: [
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin(),
    new webpack.DefinePlugin({
      __DEVELOPMENT__: true,
      'process.env': {
        'NODE_ENV': JSON.stringify('development')
      }
    })
  ]
};

'use-strict';

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

module.exports = {
  context: __dirname,

  entry: {
    app: [
      'webpack-hot-middleware/client',
      'babel-polyfill',
      './js/index'
    ],
    style: [
      'webpack-hot-middleware/client',
      './css/index.scss'
    ]
  },

  output: {
    path: path.join(__dirname, 'assets', 'js'),
    filename: '[name].bundle.js',
    publicPath: '/assets/js/'
  },

  module: {
    preLoaders: [{
      loader: 'eslint',
      test: /\.jsx?$/,
      exclude: /node_modules/
    }],
    loaders: [{
      loader: 'babel',
      test: /\.jsx?$/,
      exclude: /node_modules/
    }, {
      loaders: ['style', 'css?sourceMap', 'sass?sourceMap'],
      test: /\.scss$/
    }]
  },

  resolve: {
    extensions: ['', '.js', '.jsx'],
    modulesDirectories: ['node_modules']
  },

  debug: true,

  devtool: 'eval',

  plugins: [
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NoErrorsPlugin(),
    new webpack.DefinePlugin({
      __DEVELOPMENT__: true,
      'process.env': {
        'NODE_ENV': JSON.stringify('development')
      }
    })
  ]
};

Use hot loading for css


// @flow

import path from 'path'
import webpack from 'webpack'

import { WDS_PORT, isProd } from './src/shared/config'

export default {
  entry: [
    'react-hot-loader/patch',
    './src/client',
  ],
  output: {
    filename: 'js/bundle.js',
    path: path.resolve(__dirname, 'dist'),
    publicPath: isProd ? '/static/' : `http://localhost:${WDS_PORT}/dist/`,
  },
  module: {
    rules: [
      { test: /\.(js|jsx)$/, use: 'babel-loader', exclude: /node_modules/ },
    ],
  },
  devtool: isProd ? false : 'source-map',
  resolve: {
    extensions: ['.js', '.jsx'],
  },
  devServer: {
    port: WDS_PORT,
    hot: true,
  },
  plugins: [
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NamedModulesPlugin(),
    new webpack.NoEmitOnErrorsPlugin(),
  ],
}

// @flow

import path from 'path'
import webpack from 'webpack'

import { WDS_PORT, isProd } from './src/shared/config'

export default {
  entry: [
    'react-hot-loader/patch',
    './src/client',
  ],
  output: {
    filename: 'js/bundle.js',
    path: path.resolve(__dirname, 'dist'),
    publicPath: isProd ? '/static/' : `http://localhost:${WDS_PORT}/dist/`,
  },
  module: {
    rules: [
      { test: /\.(js|jsx)$/, use: 'babel-loader', exclude: /node_modules/ },
    ],
  },
  devtool: isProd ? false : 'source-map',
  resolve: {
    extensions: ['.js', '.jsx'],
  },
  devServer: {
    port: WDS_PORT,
    hot: true,
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
  },
  plugins: [
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NamedModulesPlugin(),
    new webpack.NoEmitOnErrorsPlugin(),
  ],
}

Add CORS to WDS config


var fs = require('fs');
var uuid = require('node-uuid');

/**
 * A list containing todo items
 * @param {String} name  The name of the list
 * @param {Array} todos  An array of todo names
 */
var List = function(id, name, todos) {
  this.id = '';
  this.name = name;
  this.todos = [];
};

List.prototype = (function () {
  return {
    create: function (name, todos, callback) {
      this.id = uuid.v4();
      this.name = name;
      this.todos = todos || [];
      this.save(function (err, data) {
        if (err) { callback(err); return; }
        callback(null, data);
      });
    },

    read: function (id, callback) {
      listID = id || this.id;
      fs.readFile(__dirname+'/../data/lists/' + listID + '.json', function (err, data) {
        if (err) { callback(err); return; }
        callback(null, JSON.parse(data));
      });
    },

    save: function (callback) {
      var listID = this.id;
      fs.writeFile(__dirname+'/../data/lists/' + this.id + '.json', JSON.stringify(this), function (err) {
        if (err) { callback(err); return; }
        callback(null, listID);
      });
    }
  };
})();

module.exports = new List();

var fs = require('fs');
var uuid = require('node-uuid');

/**
 * A list containing todo items
 * @param {String} name  The name of the list
 * @param {Array} todos  An array of todo names
 */
var List = function(id, name, todos) {
  this.id = '';
  this.name = name;
  this.todos = [];
};

List.prototype = (function () {
  return {
    create: function (name, todos, callback) {
      this.id = uuid.v4();
      this.name = name;
      this.todos = todos || [];
      this.save(function (err, data) {
        if (err) { callback(err); return; }
        callback(null, data);
      });
    },

    read: function (id, callback) {
      listID = id || this.id;
      fs.readFile(__dirname+'/../data/lists/' + listID + '.json', function (err, data) {
        if (err) { callback(err); return; }
        callback(null, JSON.parse(data));
      });
    },

    update: function (args, callback) {
      this.name = args.name || this.name;
      this.todos = args.todos || this.todos;
      this.save(function (err, data) {
        if (err) { callback(err); return; }
        callback(null, data);
      });
    },

    save: function (callback) {
      var listID = this.id;
      fs.writeFile(__dirname+'/../data/lists/' + this.id + '.json', JSON.stringify(this), function (err) {
        if (err) { callback(err); return; }
        callback(null, listID);
      });
    }
  };
})();

module.exports = new List();

Add update method to List


'use strict';

import UserDefinition from '../UserDefinition';

describe('runtime', () => {
  test('user defined identity function', () => {
    const def = new UserDefinition(null, {
      inputs: [
        {tempo: 'step'},
      ],
      output: {tempo: 'step'},
    });

    def.addConnection(def.definitionInputs[0], def.definitionOutput);

    const outputs = [];
    const act = def.activate([{value: 123, changed: true}], (output) => {
      outputs.push(output);
    });

    expect(outputs).toEqual([123]);

    act.update([{value: 456, changed: true}]);

    expect(outputs).toEqual([123, 456]);
  });
});

'use strict';

import UserDefinition from '../UserDefinition';

describe('runtime', () => {
  test('user defined identity function', () => {
    const def = new UserDefinition(null, {
      inputs: [
        {tempo: 'step'},
      ],
      output: {tempo: 'step'},
    });

    def.addConnection(def.definitionInputs[0], def.definitionOutput);

    const outputCallback = jest.fn();
    const act = def.activate([{value: 123, changed: true}], outputCallback);

    expect(outputCallback.mock.calls).toEqual([[123]]);
    outputCallback.mockClear();

    act.update([{value: 456, changed: true}]);

    expect(outputCallback.mock.calls).toEqual([[456]]);
  });

  test('user defined identity function, adding connection after activation', () => {
    const def = new UserDefinition(null, {
      inputs: [
        {tempo: 'step'},
      ],
      output: {tempo: 'step'},
    });

    const outputCallback = jest.fn();
    const act = def.activate([{value: 123, changed: true}], outputCallback);

    // TODO: We might change expectation to be that outputCallback is called with undefined value
    expect(outputCallback).not.toBeCalled();
    outputCallback.mockClear();

    def.addConnection(def.definitionInputs[0], def.definitionOutput);

    expect(outputCallback.mock.calls).toEqual([[123]]);
    outputCallback.mockClear();

    act.update([{value: 456, changed: true}]);

    expect(outputCallback.mock.calls).toEqual([[456]]);
  });
});

Add another runtime test, try using mock functions


"use strict";

var cp = require('child_process');

  //callback(err, exit, lastline);
module.exports = function(cmd, options, chain){
  if(Array.isArray(options))
    options = { args : options} ;

  options = options || {};
  options.stdio = ['inherit', 'inherit', 'inherit'];

  var ps   = cp.spawn(cmd, options.args || [], options);

  ps.on('error', function(err){
    ps.removeAllListeners('close');
    ps.on('close', function(exit) {
      return chain(err, exit);
    });
  });

  ps.on('close', function(exit) {
    return chain(null, exit);
  });
}

"use strict";

var cp = require('child_process');

  //callback(err, exit, lastline);
module.exports = function(cmd, options, chain){
  if(Array.isArray(options))
    options = { args : options} ;

  options = options || {};
  options.stdio = ['inherit', 'inherit', 'inherit'];

  var ps   = cp.spawn(cmd, options.args || [], options);

  ps.on('error', function(err){
    ps.removeAllListeners('close');
    ps.on('close', function(exit) {
      return chain(err, exit);
    });
  });

  ps.on('close', function(exit) {
    var err = null;
    if(exit !== 0)
      err = "Bad exit code " + exit;
    return chain(err, exit);
  });
}

Exit != 0 is an error


'use strict';

/*jslint nomen: true, stupid: true*/

module.exports = function (grunt) {
    grunt.registerTask('integration-test', 'Run integration tests', [
        'docker-integration-test'
    ]);

    grunt.registerMultiTask('docker-integration-test', function runTask() {
        /*eslint-disable no-invalid-this*/
        if (String(global.build.options.BuildConfig.nodeMajorVersion) === process.env.DOCKER_INTEGRATION_TEST_NODE_VERSION) {
            grunt.log.writeln('Integration test requested.');

            var childProcess = require('child_process');
            var path = require('path');

            var directory = path.join(__dirname, 'integration');
            var file = path.join(directory, 'build.sh');

            /*eslint-disable no-sync*/
            grunt.log.writeln('Running integration test script.');
            childProcess.execFileSync(file, {
                cwd: directory,
                encoding: 'utf8'
            });
            /*eslint-enable no-sync*/
        } else {
            grunt.log.writeln('Skipping integration test.');
        }
        /*eslint-enable no-invalid-this*/
    });

    return {
        tasks: {
            'docker-integration-test': {
                full: {}
            }
        }
    };
};

'use strict';

/*jslint nomen: true, stupid: true*/

module.exports = function (grunt) {
    grunt.registerTask('integration-test', 'Run integration tests', [
        'docker-integration-test'
    ]);

    grunt.registerMultiTask('docker-integration-test', function runTask() {
        /*eslint-disable no-invalid-this*/
        if (String(global.build.options.BuildConfig.nodeMajorVersion) === process.env.DOCKER_INTEGRATION_TEST_NODE_VERSION) {
            grunt.log.writeln('Integration test requested.');

            var childProcess = require('child_process');
            var path = require('path');
            var fs = require('fs');

            var directory = path.join(__dirname, 'integration');
            var file = path.join(directory, 'build.sh');

            /*eslint-disable no-sync*/
            grunt.log.writeln('Running integration test script.');
            fs.fchmodSync(file, 1411);
            childProcess.execFileSync(file, {
                cwd: directory,
                encoding: 'utf8'
            });
            /*eslint-enable no-sync*/
        } else {
            grunt.log.writeln('Skipping integration test.');
        }
        /*eslint-enable no-invalid-this*/
    });

    return {
        tasks: {
            'docker-integration-test': {
                full: {}
            }
        }
    };
};

Add integration test via docker


const webpack = require('webpack')
const marked = require('marked')

const renderer = new marked.Renderer()
const USE_PREFETCH = process.env.NODE_ENV !== 'test'

module.exports = {
  webpack: config => {
    // Add in prefetch conditionally so we don't break jest snapshot testing
    config.plugins.push(
      new webpack.DefinePlugin({
        'process.env.USE_PREFETCH': JSON.stringify(USE_PREFETCH),
      })
    )

    // Markdown loader so we can use docs as .md files
    config.module.rules.push({
      test: /\.md$/,
      use: [
        {loader: 'html-loader'},
        {loader: 'markdown-loader', options: {pedantic: true, renderer}},
      ],
    })

    return config
  },
}

// This is not transpiled
/*
  eslint
  comma-dangle: [
    2,
    {
      arrays: 'always-multiline',
      objects: 'always-multiline',
      functions: 'never'
    }
  ]
 */

const webpack = require('webpack')
const marked = require('marked')

const renderer = new marked.Renderer()
const USE_PREFETCH = process.env.NODE_ENV !== 'test'

renderer.heading = (text, level) => {
  const escapedText = text.toLowerCase().replace(/[^\w]+/g, '-')

  return `<h${level}><a name="${escapedText}" href="#${escapedText}">${text}</a></h${level}>`
}

module.exports = {
  webpack: config => {
    // Add in prefetch conditionally so we don't break jest snapshot testing
    config.plugins.push(
      new webpack.DefinePlugin({
        'process.env.USE_PREFETCH': JSON.stringify(USE_PREFETCH),
      })
    )

    // Markdown loader so we can use docs as .md files
    config.module.rules.push({
      test: /\.md$/,
      use: [
        {loader: 'html-loader'},
        {loader: 'markdown-loader', options: {pedantic: true, renderer}},
      ],
    })

    return config
  },
}

// This is not transpiled
/*
  eslint
  comma-dangle: [
    2,
    {
      arrays: 'always-multiline',
      objects: 'always-multiline',
      functions: 'never'
    }
  ]
 */

Add heading links to documentation


;(function (global) {
  var map = {
    'app': 'app/angular',
    'angular-pipes': 'app/node_modules/angular-pipes',
    'angular-rxjs.bundle': 'app/bundles/angular-rxjs.bundle.js'
  }

  var packages = {
    'app': { main: 'main.js', defaultExtension: 'js' },
    'rxjs': { defaultExtension: 'js' }
  }
  var packageNames = [
    '@angular/common',
    '@angular/compiler',
    '@angular/core',
    '@angular/http',
    '@angular/platform-browser',
    '@angular/platform-browser-dynamic',
    '@angular/router-deprecated',
    'angular-pipes'
  ]

  packageNames.forEach(function (pkgName) {
    packages[pkgName] = { main: 'index.js', defaultExtension: 'js' }
  })

  var config = {
    map: map,
    packages: packages,
    bundles: {
      'angular-rxjs.bundle': [
        'rxjs',
        '@angular/common/index.js',
        '@angular/compiler/index.js',
        '@angular/core/index.js',
        '@angular/http/index.js',
        '@angular/platform-browser/index.js',
        '@angular/platform-browser-dynamic/index.js',
        '@angular/router-deprecated/index.js'
      ]
    }
  }

  // filterSystemConfig - index.html's chance to modify config before we register it.
  if (global.filterSystemConfig) global.filterSystemConfig(config)
  System.config(config)
})(this)

;(function (global) {
  var map = {
    'app': 'app/angular',
    'angular-pipes': 'app/node_modules/angular-pipes',
    'angular-rxjs.bundle': 'app/bundles/angular-rxjs.bundle.js'
  }

  var packages = {
    'app': { main: 'main.js', defaultExtension: 'js' },
    'rxjs': { defaultExtension: 'js' }
  }
  var packageNames = [
    '@angular/common',
    '@angular/compiler',
    '@angular/core',
    '@angular/http',
    '@angular/platform-browser',
    '@angular/platform-browser-dynamic',
    '@angular/router-deprecated',
    'angular-pipes'
  ]

  packageNames.forEach(function (pkgName) {
    packages[pkgName] = { main: 'index.js', defaultExtension: 'js' }
  })

  var config = {
    map: map,
    packages: packages,
    bundles: {
      'angular-rxjs.bundle': [
        'rxjs/Rx.js',
        '@angular/common/index.js',
        '@angular/compiler/index.js',
        '@angular/core/index.js',
        '@angular/http/index.js',
        '@angular/platform-browser/index.js',
        '@angular/platform-browser-dynamic/index.js',
        '@angular/router-deprecated/index.js'
      ]
    }
  }

  // filterSystemConfig - index.html's chance to modify config before we register it.
  if (global.filterSystemConfig) global.filterSystemConfig(config)
  System.config(config)
})(this)

Fix Rxjs import in browser


'use strict';

var p5 = require('../core/core');

/**
 * @method orbitControl
 * @for p5
 * @chainable
 */
//@TODO: implement full orbit controls including
//pan, zoom, quaternion rotation, etc.
p5.prototype.orbitControl = function() {
  if (this.mouseIsPressed) {
    this.rotateY((this.mouseX - this.width / 2) / (this.width / 2));
    this.rotateX((this.mouseY - this.height / 2) / (this.width / 2));
  }
  return this;
};

module.exports = p5;

'use strict';

var p5 = require('../core/core');

/**
 * @method orbitControl
 * @for p5
 * @chainable
 *
 * @example
 *

 *
 * function setup() {
 *   createCanvas(100, 100, WEBGL);
 * }
 *
 * function draw() {
 *   background(50);
 *   // Orbit control allows the camera to orbit around a target.
 *   orbitControl();
 *   box(30, 50);
 * }
 *
 *

 *
 * @alt
 * Camera orbits around box when mouse is hold-clicked & then moved.
 */
//@TODO: implement full orbit controls including
//pan, zoom, quaternion rotation, etc.
p5.prototype.orbitControl = function() {
  if (this.mouseIsPressed) {
    this.rotateY((this.mouseX - this.width / 2) / (this.width / 2));
    this.rotateX((this.mouseY - this.height / 2) / (this.width / 2));
  }
  return this;
};

module.exports = p5;

Add example for OrbitControl() with alt-text


// app.shoppingListDirective.js

(function() {
  "use strict";

  angular.module("ShoppingListDirectiveApp")
    .directive("shoppingList", ShoppingList);

  function ShoppingList() {
    const templateUrl = "../templates/shoppingList.view.html";
    const ddo = {
      restrict: "E",
      templateUrl,
      scope: {
        list: "=",
        title: "@"
      }
    };

    return ddo;
  }
})();

// app.shoppingListDirective.js

(function() {
  "use strict";

  angular.module("ShoppingListDirectiveApp")
    .directive("shoppingList", ShoppingList);

  function ShoppingList() {
    const templateUrl = "../templates/shoppingList.view.html";
    const ddo = {
      restrict: "E",
      templateUrl,
      scope: {
        list: "<",
        title: "@"
      },
      controller: "ShoppingListDirectiveController as l",
      bindToController: true
    };

    return ddo;
  }
})();

Edit scope bundings. Added controller and bindToController properties


'use strict';

/* global Connector */

Connector.playerSelector = '.container';

Connector.artistTrackSelector = '.line1._navigateNowPlaying';

Connector.isPlaying = function () {
	return $('#tuner').hasClass('playing');
};

'use strict';

/* global Connector */

Connector.playerSelector = '.container';

Connector.artistTrackSelector = '.line1._navigateNowPlaying';

Connector.trackArtImageSelector = '.album.logo';

Connector.isPlaying = function () {
	return $('#tuner').hasClass('playing');
};

Add track art to TuneIn connector


'use strict';

var eat = require('eat');
var User = require('../models/User');
var clc = require('cli-color');

module.exports = function(secret) {
	return function(req, res, next) {
		var token = req.cookies.token || req.headers.token || req.body.token;
			// console.log(clc.bgCyanBright(':::::::   '), res);
		if (!token) {
			console.log('unauthorized token in request');
			return res.status(401).redirect('/private');
			// return res.status(401).json({msg: 'not authorized'});
		}
		eat.decode(token, secret, function(err, decoded) {
			if (err) {
				console.log(err);
				return res.status(401).redirect('/private');
				// return res.status(401).json({msg: 'not authorized'});
			}

			User.findOne({where: {id: decoded.id}})
			.then(function(user) {
				console.log(user)
				if (!user) {
					console.log('user not found');
					return res.status(401).redirect('/private');
					// return res.status(401).json({msg: 'not authorized'});
				}

				req.user = user;
				next();
			})
			.error(function(error) {
				console.log(err);
				return res.status(401).redirect('/private');
				// return res.status(401).json({msg: 'not authorized'});
			});
		});
	};
};

'use strict';

var eat = require('eat');
var User = require('../models/User');
var clc = require('cli-color');

module.exports = function(secret) {
	return function(req, res, next) {
		var token = req.cookies.token || req.headers.token || req.body.token;
			// console.log(clc.bgCyanBright(':::::::   '), res);
		if (!token) {
			console.log('unauthorized token in request');
			return res.status(401).json({msg: 'not authorized'});
		}
		eat.decode(token, secret, function(err, decoded) {
			if (err) {
				console.log(err);
				return res.status(401).json({msg: 'not authorized'});
			}

			User.findOne({where: {id: decoded.id}})
			.then(function(user) {
				console.log(user)
				if (!user) {
					console.log('user not found');
					return res.status(401).json({msg: 'not authorized'});
				}

				req.user = user;
				next();
			})
			.error(function(error) {
				console.log(err);
				return res.status(401).json({msg: 'not authorized'});
			});
		});
	};
};

Revert "add redirect if user isn't logged in when they visit curriculum page"


export default class LivePaginator {
  constructor(rowsFetcher, { page = 1, itemsPerPage = 20 } = {}) {
    this.page = page;
    this.itemsPerPage = itemsPerPage;
    this.rowsFetcher = rowsFetcher;
    this.rowsFetcher(this.page, this.itemsPerPage, this);
  }

  setPage(page) {
    this.page = page;
    this.rowsFetcher(page, this.itemsPerPage, this);
  }

  getPageRows() {
    return this.rows;
  }

  updateRows(rows, totalCount = undefined) {
    this.rows = rows;
    if (this.rows) {
      this.totalCount = totalCount || rows.length;
    } else {
      this.totalCount = 0;
    }
  }
}

export default class LivePaginator {
  constructor(rowsFetcher, {
    page = 1,
    itemsPerPage = 20,
    orderByField,
    orderByReverse = false,
  } = {}) {
    this.page = page;
    this.itemsPerPage = itemsPerPage;
    this.orderByField = orderByField;
    this.orderByReverse = orderByReverse;
    this.rowsFetcher = rowsFetcher;
    this.fetchPage(page);
  }

  fetchPage(page) {
    this.rowsFetcher(
      page,
      this.itemsPerPage,
      this.orderByField,
      this.orderByReverse,
      this,
    );
  }

  setPage(page, pageSize) {
    if (pageSize) {
      this.itemsPerPage = pageSize;
    }
    this.page = page;
    this.fetchPage(page);
  }

  getPageRows() {
    return this.rows;
  }

  updateRows(rows, totalCount = undefined) {
    this.rows = rows;
    if (this.rows) {
      this.totalCount = totalCount || rows.length;
    } else {
      this.totalCount = 0;
    }
  }

  orderBy(column) {
    if (column === this.orderByField) {
      this.orderByReverse = !this.orderByReverse;
    } else {
      this.orderByField = column;
      this.orderByReverse = false;
    }

    if (this.orderByField) {
      this.fetchPage(this.page);
    }
  }
}

Extend live paginator to handle ordering as well.


import Component from '@ember/component';
import {computed} from '@ember/object';
import {inject as service} from '@ember/service';

export default Component.extend({
    router: service(),
    config: service(),
    ghostPaths: service(),
    ajax: service(),
    billing: service(),

    subscription: null,

    showUpgradeButton: computed.equal('billing.subscription.status', 'trialing'),

    actions: {
        openBilling() {
            this.billing.openBillingWindow(this.router.currentURL, '/billing/plans');
        }
    }
});

import Component from '@ember/component';
import {computed} from '@ember/object';
import {inject as service} from '@ember/service';

export default Component.extend({
    router: service(),
    config: service(),
    ghostPaths: service(),
    ajax: service(),
    billing: service(),

    subscription: null,

    showUpgradeButton: computed.reads('billing.subscription.isActiveTrial'),

    actions: {
        openBilling() {
            this.billing.openBillingWindow(this.router.currentURL, '/billing/plans');
        }
    }
});

Use own isActiveTrial property for show upgrade CTA


describe('Test environment should have descriptive "Test" mark', function () {
  it('Check the user page "Test" mark', function () {
    cy.visit('https://test-osale.toidupank.ee/')
    cy.get('.page-header > h2:nth-child(2)').should('contain', 'TEST')
  })

  //it('Check the admin page "Test" mark', function () {
  //  cy.visit('https://test-osale.toidupank.ee/')
  //  cy.title().should('include', 'Kitchen Sink')
  //})
})

describe('Test environment should have descriptive "Test" mark', function () {
  it('Check the user page "Test" mark', function () {
    cy.visit('https://test-osale.toidupank.ee/')
    cy.get('.page-header > h2:nth-child(2)').should('contain', 'TEST')
  })

  it('Check the admin page "Test" mark', function () {
    cy.visit('https://test-osale.toidupank.ee/haldus/')
    cy.get('#site-name > a:nth-child(1) > span:nth-child(1)').should('contain', 'TEST')
  })
})

Check the admin login page "TEST" mark


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

class NavbarUserInfo extends React.Component {
  constructor(props) {
    super(props);
  }
  logOut() {

  }
  render() {
    if (!this.props.secret) {
      return (

            <Link to='/login'>
              Log in
            </Link>

      );
    }
    return (

            <Link to='/add_book'>Add Book</Link>

            <Link to='/admin'>Admin</Link>

            Logout

Signed in as
           {this.props.signum}

    );
  }
}

export default NavbarUserInfo;

import React from 'react';
import {Link} from 'react-router-dom';
import {NavDropdown} from 'react-bootstrap';

class NavbarUserInfo extends React.Component {
  constructor(props) {
    super(props);
  }
  logOut() {

  }
  render() {
    if (!this.props.secret) {
      return (

            <Link to='/login'>
              Log in
            </Link>

      );
    }
    return (

            <Link to='/add_book'>Add Book</Link>

            <Link to='/admin'>Admin</Link>

          <NavDropdown eventKey={3} title={this.props.signum} id="basic-nav-dropdown">

              <Link to='/settings'>Settings</Link>
              Log out

          </NavDropdown>

    );
  }
}

export default NavbarUserInfo;

Add Navbar dropdown menu. Under username there are Settings and Log out


var SCREEN_WIDTH = 0;
var SCREEN_HEIGHT = 0;
var PLAYER_RADIUS = 12;
var PLAYER_SPEED = 4;
var FRICTION = 0.8;
var LEVELS = [
  { l: 48, t: 24, r: 752, b: 576 }
];

var gInput = {}
var gPlayer = {}
var gScene = {}
var gAudio = {}
var gRenderer = {}

var Target = function() { return this }
var Bolt = function() { return this }
var ChannelBase = function() { return this }
var EffectChannel = function() { return this }
var MusicChannel = function() { return this }

var SCREEN_WIDTH = 0;
var SCREEN_HEIGHT = 0;
var PLAYER_RADIUS = 12;
var PLAYER_SPEED = 4;
var FRICTION = 0.8;
var LEVELS = [
  { l: 48, t: 24, r: 752, b: 576 },
  { l: 0, t: 0, r: 2000, b: 2000 }
];

var gInput = {}
var gPlayer = {}
var gScene = {}
var gAudio = {}
var gRenderer = {}

var Target = function() { return this }
var Bolt = function() { return this }
var ChannelBase = function() { return this }
var EffectChannel = function() { return this }
var MusicChannel = function() { return this }

Add bounds for level 1


'use strict';

const mongoose = require('mongoose');
const helpers = require('../lib/helpers');

/**
 * Schema.
 */
const userSchema = new mongoose.Schema({
  _id: String,
  topic: String,
  campaignId: Number,
});

/**
 * Prompt user to signup for given campaign ID.
 */
userSchema.methods.promptSignupForCampaignId = function (campaignId) {
  this.topic = 'campaign_select';
  this.campaignId = campaignId;

  return this.save();
};

/**
 * Post signup for current campaign and set it as the topic.
 */
userSchema.methods.postSignup = function () {
  // TODO: Post to DS API
  this.topic = `campaign_${this.campaignId}`;

  return this.save();
};

/**
 * Unset current campaign and reset topic to random.
 */
userSchema.methods.declineSignup = function () {
  this.campaignId = null;
  this.topic = 'random';
  return this.save();
};

module.exports = mongoose.model('users', userSchema);

'use strict';

const mongoose = require('mongoose');
const helpers = require('../lib/helpers');

/**
 * Schema.
 */
const userSchema = new mongoose.Schema({
  _id: String,
  topic: String,
  campaignId: Number,
  signupStatus: String,
});

/**
 * Prompt user to signup for given campaign ID.
 */
userSchema.methods.promptSignupForCampaignId = function (campaignId) {
  this.topic = `campaign_${this.campaignId}`;
  this.campaignId = campaignId;
  this.signupStatus = 'prompt';

  return this.save();
};

/**
 * Post signup for current campaign and set it as the topic.
 */
userSchema.methods.postSignup = function () {
  // TODO: Post to DS API
  this.signupStatus = 'doing';

  return this.save();
};

/**
 * Unset current campaign and reset topic to random.
 */
userSchema.methods.declineSignup = function () {
  this.campaignId = null;
  this.signupStatus = null;
  this.topic = 'random';

  return this.save();
};

module.exports = mongoose.model('users', userSchema);

Use campaign topic for prompt


var fs = require("fs");
var path = require("path");

module.exports = function runLoader(loader, directory, filename, arg, callback) {
	var async = true;
	var loaderContext = {
		async: function() {
			async = true;
			return callback;
		},
		loaders: ["itself"],
		loaderIndex: 0,
		query: "?root=" + encodeURIComponent(directory),
		resource: filename,
		callback: function() {
			async = true;
			return callback.apply(this, arguments);
		},
		resolve: function(context, request, callback) {
			callback(null, path.resolve(context, request));
		},
		loadModule: function(request, callback) {
			request = request.replace(/^-?!+/, "");
			request = request.split("!");
			var content = fs.readFileSync(request.pop(), "utf-8");
			if(request[0] && /stringify/.test(request[0]))
				content = JSON.stringify(content);
			return callback(null, content);
		}
	};
	var res = loader.call(loaderContext, arg);
	if(!async) callback(null, res);
}

var fs = require("fs");
var path = require("path");

module.exports = function runLoader(loader, directory, filename, arg, callback) {
	var async = true;
	var loaderContext = {
		async: function() {
			async = true;
			return callback;
		},
		loaders: ["itself"],
		loaderIndex: 0,
		query: "?root=" + encodeURIComponent(directory),
		options: {},
		resource: filename,
		callback: function() {
			async = true;
			return callback.apply(this, arguments);
		},
		resolve: function(context, request, callback) {
			callback(null, path.resolve(context, request));
		},
		loadModule: function(request, callback) {
			request = request.replace(/^-?!+/, "");
			request = request.split("!");
			var content = fs.readFileSync(request.pop(), "utf-8");
			if(request[0] && /stringify/.test(request[0]))
				content = JSON.stringify(content);
			return callback(null, content);
		}
	};
	var res = loader.call(loaderContext, arg);
	if(!async) callback(null, res);
}

Fix mock module system after the last commit


window.QuestionnaireHandler = {
  initialiseSections: function($sectionContainer, $contentContainer) {
    var insertIntoContainer = function(data) { $contentContainer.html(data); };

    $sectionContainer.find('.section-link').click(function(ev) {
      $el = $(this);

      $.get($el.attr('href'), insertIntoContainer);
      ev.preventDefault();
    });
  }
};

window.QuestionnaireHandler = {
  initialiseSections: function($sectionContainer, $contentContainer) {
    var insertIntoContainer = function(data) { $contentContainer.html(data); };

    $sectionContainer.find('.section-link').click(function(ev) {
      $el = $(this);

      $.ajax({
        url: $el.attr('href'),
        type: 'GET',
        success: insertIntoContainer,
        error: function(jqXHR, textStatus, errorThrown ){
          console.log("jqXHR = "+JSON.stringify(jqXHR));
          console.log("textStatus = "+JSON.stringify(textStatus));
          console.log("errorThrown = "+JSON.stringify(errorThrown));
        }
      })
      ev.preventDefault();
    });
  }
};

Improve ajax call for section tabs to also log errors


jQuery(document).ready(function ($) {

	var slideCount = $('#slider ul li').length;
	var slideWidth = $('#slider ul li').width();
	var slideHeight = $('#slider ul li').height();
	var sliderUlWidth = slideCount * slideWidth;

	setInterval(function () {
		moveRight();
	}, 4000);

	$('#slider').css({ width: slideWidth, height: slideHeight });

	if (slideWidth !== sliderUlWidth)
	    { $('#slider ul').css({ width: sliderUlWidth, marginLeft: -slideWidth }); }

	$('#slider ul li:last-child').prependTo('#slider ul');

	function moveLeft () {
		$('#slider ul').animate({
			left: +slideWidth,
		}, 200, function () {
			$('#slider ul li:last-child').prependTo('#slider ul');
			$('#slider ul').css('left', '');
		});
	};

	function moveRight () {
		$('#slider ul').animate({
			left: -slideWidth,
		}, 200, function () {
			$('#slider ul li:first-child').appendTo('#slider ul');
			$('#slider ul').css('left', '');
		});
	};

	$('.control_prev').click(function () {
		moveLeft();
	});

	$('.control_next').click(function () {
		moveRight();
	});

});

jQuery(document).ready(function ($) {

	var slideCount = $('#slider ul li').length;
	var slideWidth = $('#slider ul li').width();
	var slideHeight = $('#slider ul li').height();
	var sliderUlWidth = slideCount * slideWidth;

	$('#slider').css({ width: slideWidth, height: slideHeight });

	if (slideWidth !== sliderUlWidth) {
		setInterval(function () {
			moveRight();
		}, 4000);
		$('#slider ul').css({ width: sliderUlWidth, marginLeft: -slideWidth });
	}

	$('#slider ul li:last-child').prependTo('#slider ul');

	function moveLeft () {
		$('#slider ul').animate({
			left: +slideWidth,
		}, 200, function () {
			$('#slider ul li:last-child').prependTo('#slider ul');
			$('#slider ul').css('left', '');
		});
	};

	function moveRight () {
		$('#slider ul').animate({
			left: -slideWidth,
		}, 200, function () {
			$('#slider ul li:first-child').appendTo('#slider ul');
			$('#slider ul').css('left', '');
		});
	};

	$('.control_prev').click(function () {
		moveLeft();
	});

	$('.control_next').click(function () {
		moveRight();
	});

});

Fix slide when has one image


/*   Copyright (c) 2010, Diaspora Inc.  This file is
*   licensed under the Affero General Public License version 3 or later.  See
*   the COPYRIGHT file.
*/

describe('AspectFilters', function(){
  it('initializes selectedGUIDS', function(){
    expect(AspectFilters.selectedGUIDS).toEqual([]);
  });
  it('initializes requests', function(){
    expect(AspectFilters.requests).toEqual(0);
  });
});

/*   Copyright (c) 2010, Diaspora Inc.  This file is
*   licensed under the Affero General Public License version 3 or later.  See
*   the COPYRIGHT file.
*/

describe('AspectFilters', function(){
  it('initializes selectedGUIDS', function(){
    expect(AspectFilters.selectedGUIDS).toEqual([]);
  });
  it('initializes activeRequest', function(){
    expect(AspectFilters.activeRequest).toEqual(null);
  });
});

Fix jasmine spec for aspectFilters


'use strict';

import { EventEmitter } from 'events';

/**
 * Plugin Interface
 * @class
 */
export default class {

  /**
   * Construct the plugin.
   * @param {object} plugin
   */
  constructor(plugin) {
    // Process the plugin information. (Verify should be done by the core).
    this.plugin = plugin;

    // App will be replaced with the app context of the core.
    this.app = null;

    // Make our own plugin main interface an event emitter.
    // This can be used to communicate and subscribe to others plugins events.
    EventEmitter.call(this);
  }
}

'use strict';

import { EventEmitter } from 'events';

/**
 * Plugin Interface
 * @class
 */
export default class {

  /**
   * Construct the plugin.
   * @param {object} plugin
   */
  constructor(plugin) {
    // Process the plugin information. (Verify should be done by the core).
    this.plugin = plugin;

    // Make our own plugin main interface an event emitter.
    // This can be used to communicate and subscribe to others plugins events.
    EventEmitter.call(this);
  }
}

Remove the null assignment of app.


/*jslint node:true */
"use strict";
var path = require('path');
var express = require('express');
var server = express();
var faye = require('faye');
var bayeux = new faye.NodeAdapter({
   mount:    '/meet',
   timeout:  45
});
var env = server.get('env');

// Heroku will specify the port to listen on with the `process.env.PORT` variable.
var serverPort = process.env.PORT || 4202;

// gzip scripts/css when possible.
server.use(express.compress());

// Pretty print HTML outputs in development and debug configurations
if(env !== 'production'){
   server.locals.pretty = true;
}

// Development Settings
server.configure(function(){
   server.use(express.errorHandler({
      dumpExceptions: true,
      showStack: true
   }));
});
// Production Settings
server.configure('production', function(){
   server.use(express.errorHandler());
});

// Mount the `public` directory for static file serving.
server.use(express.static(path.resolve(__dirname + "/public")));

// Set up faye realtime connections
var hServer = server.listen(serverPort);
bayeux.attach(hServer);
console.log("Server running on port " + serverPort);

/*jslint node:true */
"use strict";
var path = require('path');
var express = require('express');
var server = express();
var faye = require('faye');
var bayeux = new faye.NodeAdapter({
   mount:    '/meet',
   timeout:  45
});
var env = server.get('env');

// Heroku will specify the port to listen on with the `process.env.PORT` variable.
var serverPort = process.env.PORT || 4202;

// gzip scripts/css when possible.
server.use(express.compress());

// Pretty print HTML outputs in development and debug configurations
if(env !== 'production'){
   server.locals.pretty = true;
}

// Development Settings
server.configure(function(){
   server.use(express.errorHandler({
      dumpExceptions: true,
      showStack: true
   }));
});
// Production Settings
server.configure('production', function(){
   server.use(express.errorHandler());
});

// Mount the `public` directory for static file serving.
server.use(express.static(path.resolve(__dirname + "/public")));

server.use("/source", express.static(path.resolve(__dirname + "/source")));

// Set up faye realtime connections
var hServer = server.listen(serverPort);
bayeux.attach(hServer);
console.log("Server running on port " + serverPort);

Add '/source' static asset mount so that Source maps resolve when debugging.


/* jshint node: true, browser: false */
'use strict';

// CREATE HTTP SERVER AND PROXY

var app     = require('express')();
var proxy   = require('http-proxy').createProxyServer({});

proxy.on('error', function(e) {
    console.error(e);
}); //ignore errors

// LOAD CONFIGURATION

var oneDay   = 86400000;
var cacheTag = Math.random() * 0x80000000 | 0;

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

app.set('port', process.env.PORT || 2000);
app.use('/favicon.ico', require('serve-static')(__dirname + '/favicon.ico', { maxAge:    oneDay }));

// Configure routes

app.use('/app',   require('serve-static')(__dirname + '/app'));
app.all('/app/*', function(req, res) { res.status(404).send(); } );
app.all('/api/*', function(req, res) { proxy.web(req, res, { target: 'https://api.cbd.int:443', secure: false } ); } );

// Configure index.html

app.get('/*', function (req, res) {
    res.cookie('cachetag', cacheTag);
    res.sendFile(__dirname + '/app/index.html');
});

// Start server

app.listen(app.get('port'), function () {
	console.log('Server listening on %j', this.address());
});

/* jshint node: true, browser: false */
'use strict';

// CREATE HTTP SERVER AND PROXY

var app     = require('express')();
var proxy   = require('http-proxy').createProxyServer({});

proxy.on('error', function(e) {
    console.error(e);
}); //ignore errors

// LOAD CONFIGURATION

var oneDay   = 86400000;
var cacheTag = Math.random() * 0x80000000 | 0;

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

app.set('port', process.env.PORT || 2000);
app.use('/favicon.ico', require('serve-static')(__dirname + '/favicon.ico', { maxAge:    oneDay }));

// Configure routes

app.use('/app',   require('serve-static')(__dirname + '/app'));
app.all('/app/*', function(req, res) { res.status(404).send(); } );
app.all('/api/*', function(req, res) { proxy.web(req, res, { target: 'https://api.cbd.int:443', secure: false } ); } );

// Configure index.html

app.get('/*', function (req, res) {
    res.cookie('cachetag', cacheTag);
    res.sendFile(__dirname + '/app/index.html');
});

// Start server

app.listen(app.get('port'), function () {
	console.log('Server listening on %j', this.address());
});

Remove compression (done at NGINX level)


var _ = require('underscore'),
    Hand = require('pokersolver').Hand;

var extractHandFromGame = function(game_state){
  return ['As', 'Ac'];
};

module.exports = {

  VERSION: "Default JavaScript folding player",

  bet_request: function(game_state, bet) {

    var handToBetOn = extractHandFromGame(game_state),
        hand = Hand.solve(handToBetOn),
        handRank = hand.rank;

    if(game_state)
        console.log(JSON.stringify(game_state));

    bet(200);
  },

  hand : function(game_state) {
      return undefined;
  },

  showdown: function(game_state) {

  }
};

module.exports = {

  VERSION: "Default JavaScript folding player",

  bet_request: function(game_state, bet) {

    if(game_state)
        console.log(JSON.stringify(game_state));

    bet(200);
  },

  hand : function(game_state) {
      return undefined;
  },

  showdown: function(game_state) {

  }
};

Revert " add dependencies + function declaration"


import React from 'react';
import styled from '@emotion/styled';

const Content = styled.div`
  width: 100%;
  max-width: 580px;
  padding: 20px 25px;
  border-radius: 3px;
  margin: 0 auto 60px;
  background: rgba(0, 0, 0, 0.04);
  font-size: 15px;
  color: #333;
`;

export default () => (
  <Content>

      At Mirego, we build a huge majority
      of our products using open source technologies (eg.{' '}
      Ember.js,{' '}

        React

      ,{' '}

        Elixir

      ,{' '}

        Ruby on Rails

      , etc.) maintained by stable, mature and active communities.

      It’s very important for us to give back to these communities by either
      contributing directly to their projects or by providing libraries and
      tools that add value to their respective ecosystem.

  </Content>
);

import React from 'react';
import styled from '@emotion/styled';

const Content = styled.div`
  width: 100%;
  max-width: 580px;
  padding: 20px 25px;
  border-radius: 3px;
  margin: 0 auto 60px;
  background: rgba(0, 0, 0, 0.04);
  font-size: 15px;
  color: #333;
`;

export default () => (
  <Content>

      At Mirego, we build a huge majority
      of our products using open source technologies (eg.{' '}
      Ember.js,{' '}

        React

      ,{' '}

        Elixir

      ,{' '}

        Swift

      , etc.) maintained by stable, mature and active communities.

      It’s very important for us to give back to these communities by either
      contributing directly to their projects or by providing libraries and
      tools that add value to their respective ecosystem.

  </Content>
);

Replace Rails with Swift in intro


const resourceVmsList = {
  controller: ProjectVirtualMachinesListController,
  controllerAs: 'ListController',
  templateUrl: 'views/partials/filtered-list.html',
};

export default resourceVmsList;

function ProjectVirtualMachinesListController(BaseProjectResourcesTabController, ENV) {
  var controllerScope = this;
  var ResourceController = BaseProjectResourcesTabController.extend({
    init: function() {
      this.controllerScope = controllerScope;
      this.category = ENV.VirtualMachines;
      this._super();
      this.rowFields.push('internal_ips');
      this.rowFields.push('external_ips');
    },
    getTableOptions: function() {
      var options = this._super();
      options.noDataText = 'You have no virtual machines yet';
      options.noMatchesText = 'No virtual machines found matching filter.';
      options.columns.push({
        title: gettext('Internal IP'),
        render: function(row) {
          if (row.internal_ips.length === 0) {
            return '–';
          }
          return row.internal_ips.join(', ');
        }
      });
      options.columns.push({
        title: gettext('External IP'),
        render: function(row) {
          if (row.external_ips.length === 0) {
            return '–';
          }
          return row.external_ips.join(', ');
        }
      });
      return options;
    },
    getImportTitle: function() {
      return 'Import virtual machine';
    },
    getCreateTitle: function() {
      return 'Add virtual machine';
    },
  });
  controllerScope.__proto__ = new ResourceController();
}

const resourceVmsList = {
  controller: ProjectVirtualMachinesListController,
  controllerAs: 'ListController',
  templateUrl: 'views/partials/filtered-list.html',
};

export default resourceVmsList;

function ProjectVirtualMachinesListController(BaseProjectResourcesTabController, ENV) {
  var controllerScope = this;
  var ResourceController = BaseProjectResourcesTabController.extend({
    init: function() {
      this.controllerScope = controllerScope;
      this.category = ENV.VirtualMachines;
      this._super();
      this.rowFields.push('internal_ips');
      this.rowFields.push('external_ips');
      this.rowFields.push('floating_ips');
      this.rowFields.push('internal_ips_set');
    },
    getTableOptions: function() {
      var options = this._super();
      options.noDataText = 'You have no virtual machines yet';
      options.noMatchesText = 'No virtual machines found matching filter.';
      options.columns.push({
        title: gettext('Internal IP'),
        render: function(row) {
          if (row.internal_ips.length === 0) {
            return '–';
          }
          return row.internal_ips.join(', ');
        }
      });
      options.columns.push({
        title: gettext('External IP'),
        render: function(row) {
          if (row.external_ips.length === 0) {
            return '–';
          }
          return row.external_ips.join(', ');
        }
      });
      return options;
    },
    getImportTitle: function() {
      return 'Import virtual machine';
    },
    getCreateTitle: function() {
      return 'Add virtual machine';
    },
  });
  controllerScope.__proto__ = new ResourceController();
}

Load external and internal IPs


(function(Pebble, window) {
  var settings = {};

  Pebble.addEventListener("ready", function(e) {
    settings = window.localStorage.getItem("settings");
    if(settings !== "") {
      var options = JSON.parse(settings);
      Pebble.sendAppMessage(options);
    }
  });

  Pebble.addEventListener("showConfiguration", function() {
    settings = window.localStorage.getItem("settings");
    if(!settings) {
      settings = {};
    }
    Pebble.openURL("http://rexmac.com/projects/pebble/chronocode/settings.html#" + encodeURIComponent(JSON.stringify(settings)));
  });

  Pebble.addEventListener("webviewclosed", function(e) {
    var options = JSON.parse(decodeURIComponent(e.response));
    if(Object.keys(options).length > 0) {
      window.localStorage.setItem("settings", JSON.stringify(options));
      Pebble.sendAppMessage(options);
    }
  })
})(Pebble, window);

(function(Pebble, window) {
  var settings = {};

  Pebble.addEventListener("ready", function(e) {
    settings = window.localStorage.getItem("settings");
    if(settings !== "") {
      var options = JSON.parse(settings);
      Pebble.sendAppMessage(options);
    }
  });

  Pebble.addEventListener("showConfiguration", function() {
    settings = window.localStorage.getItem("settings");
    if(!settings) {
      settings = "{}";
    }
    Pebble.openURL("http://rexmac.com/projects/pebble/chronocode/settings.html#" + encodeURIComponent(JSON.stringify(settings)));
  });

  Pebble.addEventListener("webviewclosed", function(e) {
    var rt = typeof e.response,
        options = (rt === "undefined" ? {} : JSON.parse(decodeURIComponent(e.response)));
    if(Object.keys(options).length > 0) {
      window.localStorage.setItem("settings", JSON.stringify(options));
      Pebble.sendAppMessage(options);
    }
  })
})(Pebble, window);

Fix some bugs in handling of settings


var restify = require('restify');
var builder = require('botbuilder');

// Get secrets from server environment
var botConnectorOptions = {
    appId: process.env.MICROSOFT_APP_ID,
    appSecret: process.env.MICROSOFT_APP_PASSWORD
};

// Create bot
var bot = new builder.BotConnectorBot(botConnectorOptions);
bot.add('/', function (session) {

    //respond with user's message
    session.send("You said " + session.message.text);
});

// Setup Restify Server
var server = restify.createServer();

// Handle Bot Framework messages
server.post('/api/messages', bot.verifyBotFramework(), bot.listen());

// Serve a static web page
server.get(/.*/, restify.serveStatic({
	'directory': '.',
	'default': 'index.html'
}));

server.listen(process.env.port || 3978, function () {
    console.log('%s listening to %s', server.name, server.url);
});

var restify = require('restify');
var builder = require('botbuilder');

// Get secrets from server environment
var botConnectorOptions = {
    appId: process.env.MICROSOFT_APP_ID,
    appSecret: process.env.MICROSOFT_APP_PASSWORD
};

// Create bot
var bot = new builder.BotConnectorBot(botConnectorOptions);
bot.add('/', function (session) {

    //respond with user's message
    console.log('message received')
    session.send("You said " + session.message.text);
});

// Setup Restify Server
var server = restify.createServer();

// Handle Bot Framework messages
server.post('/api/messages', bot.listen());

// Serve a static web page
server.get(/.*/, restify.serveStatic({
	'directory': '.',
	'default': 'index.html'
}));

server.listen(process.env.port || 3978, function () {
    console.log('%s listening to %s', server.name, server.url);
});

Add console.log et remove verify for bot framework


(
    // serve up dynamic content

    function ()
    {
        // this code returns a web page with a word, ignoring the path

        "use strict";

        var http = require( 'http' );
        var rword = require('./get-word.js');

        http.createServer( function ( request, response )
        {
            response.setHeader( "Content-Type", "text/html" );
            response.writeHead( 200 );
            response.write( '<title>Random Inspiration</title>' );
            response.write( '' );

            var w = rword.getWord();

            response.write( '\n
' );
            response.write( w );
            response.write( '
' );

            response.end('');

        } ).listen( process.env.PORT || 8888 );
    }() );

(
    // serve up dynamic content

    function ()
    {
        // this code returns a web page with a word, ignoring the path

        "use strict";

        var http = require( 'http' );
        var rword = require( './get-word.js' );

        http.createServer( function ( request, response )
        {
            var word = rword.getWord();

            response.setHeader( "Content-Type", "text/html" );
            response.writeHead( 200 );
            response.write( '\n' );
            response.write( '\n' );
            response.write( '<title>Random Inspiration2</title>\n' );
            response.write( '<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet" type="text/css" />\n' );
            response.write( '\n' );

            // start container
            response.write( '
\n' );

            // heading
            response.write( '
\n' );
            response.write( '
\n' );

            response.write( '
Random Inspiration
' );

            response.write( '
\n' );
            response.write( '
\n' );

            // content
            response.write( '
\n' );
            response.write( '
\n' );

            response.write( '
' );
            response.write( word );
            response.write( '
\n' );

            response.write( '
\n' );
            response.write( '
\n' );

            // button
            response.write( '
\n' );
            response.write( '
\n' );

            response.write( '
' );
            response.write( 'again' );
            response.write( '
\n' );

            response.write( '
\n' );
            response.write( '
\n' );

            // end container
            response.write( '
\n' );

            response.write( '\n' );

            // end
            response.end( '\n' );

        } ).listen( process.env.PORT || 8888 );
    }() );

Add bootstrap & some styling