/* global angular, console */

(function () {
    'use strict';

    angular
        .module('plotWidget')
        .controller('PlotWidgetController', PlotWidgetController);

    PlotWidgetController.$inject = ['$scope', 'weatherRestService'];

    function PlotWidgetController($scope, weatherRestService) {
        var vm = this;

        init();

        // ####################################################################

        function init() {
            $scope.plotOptions = {
                showRangeSelector: true,
                title: $scope.quantity,
                color: 'rgb(42, 101, 212)',
                gridLineColor: 'rgb(200, 200, 200)',
                rangeSelectorPlotFillColor: '#575df5',
                rangeSelectorPlotStrokeColor: '#676877'
            };
        }

        weatherRestService.data('2014-08-30', '2014-08-31', $scope.quantity)
//        weatherRestService.data(null, null, 'inHumidity')
            .then(function(data) {
            var newData = [];

            for(var i=0, len=data.data.timePoints.length; i<len; ++i) {
                newData.push([new Date(data.data.timePoints[i]), data.data.dataPoints[i]]);
            }

            $scope.plotData = newData;
        });

    }
}());

/* global angular, console */

(function () {
    'use strict';

    angular
        .module('plotWidget')
        .controller('PlotWidgetController', PlotWidgetController);

    PlotWidgetController.$inject = ['$scope', 'weatherRestService'];

    function PlotWidgetController($scope, weatherRestService) {
        var vm = this;

        init();

        // ####################################################################

        function init() {
            $scope.plotOptions = {
                showRangeSelector: true,
                title: $scope.quantity,
                color: 'rgb(42, 101, 212)',
                gridLineColor: 'rgb(200, 200, 200)',
                rangeSelectorPlotFillColor: '#575df5',
                rangeSelectorPlotStrokeColor: '#676877'
            };
        }

        weatherRestService.data('2014-08-30', '2014-09-30', $scope.quantity)
//        weatherRestService.data(null, null, $scope.quantity)
            .then(function(data) {
            var newData = [],
                conversionFunc = function(v) { return v; };

            if(/temp/i.test($scope.quantity)) {
                conversionFunc = function(v) { return (v-32)/1.8; };
                $scope.plotOptions.ylabel = "Celsius";
            }

            for(var i=0, len=data.data.timePoints.length; i<len; ++i) {
                newData.push([new Date(data.data.timePoints[i]), conversionFunc(data.data.dataPoints[i])]);
            }

            $scope.plotData = newData;
        });

    }
}());

Convert temperatures to degrees Celsius.


'use strict';

// Configuring the Groups module
angular.module('groups').run(['Menus', function (Menus) {
	// Add the dropdown manage groups
	Menus.addSubMenuItem('topbar', 'admin', {
		title: 'Groupes',
		state: 'admin.groups',
		roles: ['admin']
	});
}]);

'use strict';

// Configuring the Groups module
angular.module('groups').run(['Menus', function (Menus) {
	// Add the dropdown manage groups
	Menus.addSubMenuItem('topbar', 'admin', {
		title: 'Groupes',
		state: 'admin.groups.list',
		roles: ['admin']
	});
}]);

Fix routing bug in groups module


/**
 * The Logging layer module.
 *
 * @return LoggingLayer class (extends CartoDBLayerClass)
 */
define([
  'abstract/layer/CartoDBLayerClass',
], function(CartoDBLayerClass) {

  'use strict';

  var LoggingLayer = CartoDBLayerClass.extend({

    options: {
      sql: 'SELECT \'logging\' as tablename, cartodb_id, the_geom_webmercator, company, country, area_ha, name, source,status, \'{tableName}\' AS layer, {analysis} AS analysis FROM {tableName}',
      infowindow: true,
      interactivity: 'cartodb_id, tablename, name, company, country, area_ha, analysis',
      analysis: true
    }

  });

  return LoggingLayer;

});

/**
 * The Logging layer module.
 *
 * @return LoggingLayer class (extends CartoDBLayerClass)
 */
define([
  'abstract/layer/CartoDBLayerClass',
], function(CartoDBLayerClass) {

  'use strict';

  var LoggingLayer = CartoDBLayerClass.extend({

    options: {
      sql: 'SELECT \'logging\' as tablename, cartodb_id, the_geom_webmercator, company, country, permit_num, nat_origin, area_ha, name, \'{tableName}\' AS layer, {analysis} AS analysis FROM {tableName}',
      infowindow: true,
      interactivity: 'cartodb_id, tablename, name, company, country, permit_num, nat_origin, area_ha, analysis',
      analysis: true
    }
/*

sql: 'SELECT \'logging\' as tablename, cartodb_id, the_geom_webmercator, company, country, area_ha, name, source,status, \'{tableName}\' AS layer, {analysis} AS analysis FROM {tableName}',
      infowindow: true,
      interactivity: 'cartodb_id, tablename, name, company, country, area_ha, analysis',

      */
  });

  return LoggingLayer;

});

Change data logging origin fix revert


//Get the required shit together
const config = require("./config.json");
const Discord = require("discord.js");
const client = new Discord.Client();
const MSS = require("./functions/");
const fs = require("fs");

//Login to Discord
client.login(config.API.discord);

//Include all files in the commands directory
fs.readdir("./commands/", function(err, items) {
	items.forEach(function(item) {
		var file = file.replace(/['"]+/g, '');
		var command[file] = require(file);
	})
})

client.on('ready', function() {
	console.log("Successfully connected to Discord!");
	client.user.setGame(config.MSS.prefix + "help | " + config.MSS.version);
});

client.on('message', function(message) {
	if (!message.content.startsWith(config.MSS.prefix)) return false;
	let input = message.content.replace (/\n/g, "").split(" ");
	input[0] = input[0].substring(config.MSS.prefix.length);

	if (input[0] === "eval" && message.author.id === "190519304972664832") {
		eval(message.content.substring(config.MSS.prefix.length + input[0].length + 1));
	}
});

//Get the required shit together
const config = require("./config.json");
const Discord = require("discord.js");
const client = new Discord.Client();
const MSS = require("./functions/");
const fs = require("fs");
var command = [];

//Login to Discord
client.login(config.API.discord);

//Include all files in the commands directory
fs.readdir("./commands/", function(err, items) {
	items.forEach(function(item) {
		var file = file.replace(/['"]+/g, '');
		command[file] = require(file);
	})
})

client.on('ready', function() {
	console.log("Successfully connected to Discord!");
	client.user.setGame(config.MSS.prefix + "help | " + config.MSS.version);
});

client.on('message', function(message) {
	if (!message.content.startsWith(config.MSS.prefix)) return false;
	let input = message.content.replace (/\n/g, "").split(" ");
	input[0] = input[0].substring(config.MSS.prefix.length);

	if (input[0] === "eval" && message.author.id === "190519304972664832") {
		eval(message.content.substring(config.MSS.prefix.length + input[0].length + 1));
	}
});

Declare command function before use


'use strict'
const fs = require('fs');
const parsePackageString = require('npm-package-arg');
const enhancedResolve = require('enhanced-resolve');
const InstallationUtils = require('./utils/installation-utils');
const getEcmaVersionAST = require('./get-ecma-version-ast.js');

const resolve = enhancedResolve.create.sync({
    modules: ['node_modules'],
    mainFields: ['browser', 'module', 'main', 'style'],
});

function isEcmaVersionModern(ecmaVersion) {
    return ecmaVersion > 5;
}

async function getEntryPointEcmaVersion(context, packageName) {
    const resolvedPath = resolve(context, packageName);
    const code = fs.readFileSync(resolvedPath, 'utf8');
    // TODO (ISSUE#5) Implement recursive getEntryPointEcmaVersion
    return getEcmaVersion(code);
}

async function getPackageEcmaVersion(packageString) {
    const parsedPackage = parsePackageString(packageString);
    const installPath = await InstallationUtils.getInstallPath();
    await InstallationUtils.installPackage(parsedPackage.name, installPath);
    const ecmaVersion = getEntryPointEcmaVersion(installPath, parsedPackage.name);
    InstallationUtils.cleanupPath(installPath);
    return ecmaVersion;
}

function getEcmaVersion(code) {
    return getEcmaVersionAST(code);
}

module.exports = { getEcmaVersion, getPackageEcmaVersion, getEntryPointEcmaVersion, isEcmaVersionModern };

'use strict'
const fs = require('fs');
const { promisify } = require('util');
const parsePackageString = require('npm-package-arg');
const enhancedResolve = require('enhanced-resolve');
const InstallationUtils = require('./utils/installation-utils');
const getEcmaVersionAST = require('./get-ecma-version-ast.js');

const resolve = promisify(enhancedResolve.create({
    mainFields: ['module', 'browser', 'main'],
}));

function isEcmaVersionModern(ecmaVersion) {
    return ecmaVersion > 5;
}

async function getEntryPointEcmaVersion(context, packageName) {
    const resolvedPath = await resolve(context, packageName);
    const code = fs.readFileSync(resolvedPath, 'utf8');
    // TODO (ISSUE#5) Implement recursive getEntryPointEcmaVersion
    return getEcmaVersion(code);
}

async function getPackageEcmaVersion(packageString) {
    const parsedPackage = parsePackageString(packageString);
    const installPath = await InstallationUtils.getInstallPath();
    await InstallationUtils.installPackage(parsedPackage.name, installPath);
    const ecmaVersion = await getEntryPointEcmaVersion(installPath, parsedPackage.name);
    await InstallationUtils.cleanupPath(installPath);
    return ecmaVersion;
}

function getEcmaVersion(code) {
    return getEcmaVersionAST(code);
}

module.exports = { getEcmaVersion, getPackageEcmaVersion, getEntryPointEcmaVersion, isEcmaVersionModern };

Change enhanced-resolve to promisified version


"use strict";

//Load dependencies
var applicationStorage = process.require("core/applicationStorage");

/**
 * Insert a stat object
 * @param tier
 * @param raid
 * @param stat
 * @param callback
 */
module.exports.insertOne = function (tier, raid, stats, callback) {
    var collection = applicationStorage.mongo.collection("progress_stats");
    var obj = {tier: tier, raid: raid, stats: stats}
    collection.insertOne(obj, function (error) {
        callback(error);
    });
};

/**
 * Return the last stat (max 200)
 * @param raid
 * @param callback
 */
module.exports.getStats = function (tier, raid, limit, callback) {
    var collection = applicationStorage.mongo.collection("progress_stats");
    collection.find({tier: tier, raid: raid}, {stats:1})
        .sort({_id: -1})
        .limit(limit)
        .toArray(function (error, stats) {
            console.log(stats);
            callback(error, stats);
        });

};

"use strict";

//Load dependencies
var applicationStorage = process.require("core/applicationStorage");

/**
 * Insert a stat object
 * @param tier
 * @param raid
 * @param stat
 * @param callback
 */
module.exports.insertOne = function (tier, raid, stats, callback) {
    var collection = applicationStorage.mongo.collection("progress_stats");
    var obj = {tier: tier, raid: raid, stats: stats}
    collection.insertOne(obj, function (error) {
        callback(error);
    });
};

/**
 * Return the last stat (max 200)
 * @param raid
 * @param callback
 */
module.exports.getStats = function (tier, raid, limit, callback) {
    var collection = applicationStorage.mongo.collection("progress_stats");
    collection.find({tier: tier, raid: raid}, {stats:1})
        .sort({_id: 1})
        .limit(limit)
        .toArray(function (error, stats) {
            console.log(stats);
            callback(error, stats);
        });

};

Add limit on stats service


(function () {
    'use strict';

    /* ngInject */
    function ProfilesController(NavbarConfig, ProfileService) {
        var ctl = this;
        initialize();

        function initialize() {
            ProfileService.createProfile('Donald');
            ProfileService.createProfile('Mickey');
            ProfileService.createProfile('Minnie');

            ctl.usernames = ProfileService.getProfileNames();
            var title = ctl.usernames.length ? ctl.usernames[0] : 'Profile';
            NavbarConfig.set({ title: ctl.usernames[0]});
        }
    }

    angular.module('nih.views.profile')
    .controller('ProfilesController', ProfilesController);

})();

(function () {
    'use strict';

    /* ngInject */
    function ProfilesController(NavbarConfig, ProfileService) {
        var ctl = this;
        initialize();

        function initialize() {
            ProfileService.createProfile('Donald');
            ProfileService.createProfile('Mickey');
            ProfileService.createProfile('Minnie');

            ctl.usernames = ProfileService.getProfileNames();
            var title = ctl.usernames.length ? ctl.usernames[0] : 'Profile';
            NavbarConfig.set({ title: title});
        }
    }

    angular.module('nih.views.profile')
    .controller('ProfilesController', ProfilesController);

})();

Fix unused title in profiles controller


import Velocity from 'velocity-animate';

export default function vq(el, props, opts = null) {
  if (!opts) {
    opts = props.o;
    props = props.p;
  }
  opts = clone(opts);

  return function(done) {
    opts.complete = done;
    Velocity(el, props, opts);
  };
}

export function sequence(seq) {
  const head = seq[0];
  const tail = seq.slice(1);

  if (typeof head !== 'function') return;

  head(function() {
    sequence(tail);
  });
}

function clone(obj) {
  const result = {};

  Object.keys(obj).forEach(function(key) {
    if (obj[key] && typeof obj[key] === 'object') {
      result[key] = clone(obj[key]);
    } else {
      result[key] = obj[key];
    }
  });

  return result;
}

import Velocity from 'velocity-animate';

export default function vq(el, props, opts = null) {
  if (!opts) {
    opts = props.o;
    props = props.p;
  }
  opts = clone(opts);

  return function(done) {
    opts.complete = done;
    Velocity(el, props, opts);
  };
}

export function sequence(seq) {
  const head = seq[0];
  const tail = seq.slice(1);

  if (typeof head !== 'function') return;

  if (head.length > 0) {
    // Ensure there is a callback function as 1st argument
    head(function() {
      sequence(tail);
    });
  } else {
    head();
    sequence(tail);
  }
}

function clone(obj) {
  const result = {};

  Object.keys(obj).forEach(function(key) {
    if (obj[key] && typeof obj[key] === 'object') {
      result[key] = clone(obj[key]);
    } else {
      result[key] = obj[key];
    }
  });

  return result;
}

Handle both synchronous and asynchronous processing


//@flow
import React from "react";
import ReactDOM from "react-dom";

import { Provider } from "react-redux";
import { Route } from "react-router";
import { ConnectedRouter as Router } from "react-router-redux";

import store, { history } from "./store";

import App from "./App";

declare var module: {
  hot: {
    accept(path: Class<React$Component<*, *, *>>, callback: () => void): void
  }
};

const render = Component => {
  return ReactDOM.render(
    <Provider store={store}>
      <Router history={history}>
        <Route path="/" component={Component} />
      </Router>
    </Provider>,
    document.getElementById("root")
  );
};

render(App);

if (module.hot) {
  module.hot.accept(App, () => {
    const NextApp = require("./App").default;
    render(NextApp);
  });
}

//@flow
import React from "react";
import ReactDOM from "react-dom";

import { Provider } from "react-redux";
import { Route } from "react-router";
import { ConnectedRouter } from "react-router-redux";
import store, { history } from "./store";

import App from "./App";

const render = (Component: any) => {
  return ReactDOM.render(
    <Provider store={store}>
      <ConnectedRouter history={history}>
        <Route path="/" component={Component} />
      </ConnectedRouter>
    </Provider>,
    document.getElementById("root")
  );
};

render(App);

if (module.hot) {
  module.hot.accept("./App", () => {
    const NextApp = require("./App").default;
    render(NextApp);
  });
}

Remove type declaration for module


var triflow = require('./core/index');
triflow.element = require('./Element/index');

module.exports = triflow;

var triflow = require('./core/index');
triflow.element = require('./element/index');

module.exports = triflow;

Fix one more cap error


import injectify from './injectify.js';

module.exports = function injectifyLoader(source, inputSourceMap) {
  if (this.cacheable) {
    this.cacheable();
  }

  const { code, map } = injectify(this, source, inputSourceMap);
  this.callback(null, code, map);
};

import injectify from './injectify.js';

export default function injectifyLoader(source, inputSourceMap) {
  if (this.cacheable) {
    this.cacheable();
  }

  const { code, map } = injectify(this, source, inputSourceMap);
  this.callback(null, code, map);
};

Use consistent module export syntax (es6).


// FIXME DocumentTouch is deprecated, see:
// https://developer.mozilla.org/en-US/docs/Web/API/DocumentTouch
/* global DocumentTouch */

import $ from 'jquery';
import angular from 'angular';

function bootstrap(module) {
  const interface_ = $('meta[name=interface]')[0].getAttribute('content');
  const dynamicUrl_ = $('meta[name=dynamicUrl]')[0].getAttribute('content');
  const dynamicUrl = `${dynamicUrl_}?interface=${interface_}&query=${encodeURIComponent(document.location.search)}`;
  const request = $.ajax(dynamicUrl, {
    'dataType': 'json',
    'xhrFields': {
      withCredentials: false
    }
  });
  request.fail((jqXHR, textStatus) => {
    window.alert(`Failed to get the dynamic: ${textStatus}`);
  });
  request.done((dynamic) => {
    if (dynamic['doRedirect']) {
      const small_screen = window.matchMedia ? window.matchMedia('(max-width: 1024px)') : false;
      if (small_screen && (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch)) {
        window.location = dynamic['redirectUrl'];
      }
    }

    for (const name in dynamic['constants']) {
      module.constant(name, dynamic['constants'][name]);
    }

    angular.bootstrap(document, [`App${interface_}`]);
  });
}

export default bootstrap;

import $ from 'jquery';
import angular from 'angular';
import {TOUCH} from 'ol/has.js';

function bootstrap(module) {
  const interface_ = $('meta[name=interface]')[0].getAttribute('content');
  const dynamicUrl_ = $('meta[name=dynamicUrl]')[0].getAttribute('content');
  const dynamicUrl = `${dynamicUrl_}?interface=${interface_}&query=${encodeURIComponent(document.location.search)}`;
  const request = $.ajax(dynamicUrl, {
    'dataType': 'json',
    'xhrFields': {
      withCredentials: false
    }
  });
  request.fail((jqXHR, textStatus) => {
    window.alert(`Failed to get the dynamic: ${textStatus}`);
  });
  request.done((dynamic) => {
    if (dynamic['doRedirect']) {
      const small_screen = window.matchMedia ? window.matchMedia('(max-width: 1024px)') : false;
      if (small_screen && TOUCH) {
        window.location = dynamic['redirectUrl'];
      }
    }

    for (const name in dynamic['constants']) {
      module.constant(name, dynamic['constants'][name]);
    }

    angular.bootstrap(document, [`App${interface_}`]);
  });
}

export default bootstrap;

Use ol.has.TOUCH to check if the device support touch events


'use strict';
var GameDataCreator = require('../gamedata');
var PointView = require('../prefabs/pointview');

function Editor() {}
Editor.prototype = {
  create: function() {
    this.game.data = new GameDataCreator.GameData();
    var background = this.game.add.sprite(0, 0, 'background');
    this.sprites = this.game.add.group();
    background.inputEnabled = true;
    background.events.onInputDown.add(this.clickListener, this);
  },
  update: function() {
  },
  clickListener: function(sprite, pointer) {
    var newPoint = new GameDataCreator.GamePoint(Math.floor(pointer.x),  Math.floor(pointer.y), 'unvisited');
    console.log(newPoint);
    this.game.data.points.push(newPoint);
    var pointSprite = new PointView(this.game, newPoint);
    this.game.add.existing(pointSprite);
    this.sprites.add(pointSprite);
    console.log(Math.floor(pointer.x) + ' ' + Math.floor(pointer.y));
    console.log(this.game.data.points);
    var textArea = window.document.getElementById('outputJSON');
    textArea.value = JSON.stringify(this.game.data, null, 2);
  }
};

module.exports = Editor;

'use strict';
var GameDataCreator = require('../gamedata');
var PointView = require('../prefabs/pointview');

function Editor() {}
Editor.prototype = {
  create: function() {
    this.game.data = new GameDataCreator.GameData();
    var background = this.game.add.sprite(0, 0, 'background');
    this.sprites = this.game.add.group();
    background.inputEnabled = true;
    background.events.onInputDown.add(this.clickListener, this);
  },
  update: function() {
  },
  clickListener: function(sprite, pointer) {
    var newPoint = new GameDataCreator.GamePoint(Math.floor(pointer.x),  Math.floor(pointer.y), 'unvisited');
    this.game.data.points.push(newPoint);
    var pointSprite = new PointView(this.game, newPoint);
    this.game.add.existing(pointSprite);
    this.sprites.add(pointSprite);
    this.updatePreviewText();
  },
  updatePreviewText: function() {
    var textArea = window.document.getElementById('outputJSON');
    textArea.value = JSON.stringify(this.game.data, null, 2);
  }
};

module.exports = Editor;

Move updating preview text to its own function


'use strict';

var BinWrapper = require('bin-wrapper');
var path = require('path');
var pkg = require('../package.json');
var url = 'https://raw.github.com/imagemin/optipng-bin/' + pkg.version + '/vendor/';

module.exports = new BinWrapper()
	.src(url + 'osx/optipng', 'darwin')
	.src(url + 'linux/x86/optipng', 'linux', 'x86')
	.src(url + 'linux/x64/optipng', 'linux', 'x64')
	.src(url + 'freebsd/optipng', 'freebsd')
	.src(url + 'sunos/x86/optipng', 'sunos', 'x86')
	.src(url + 'sunos/x64/optipng', 'sunos', 'x64')
	.src(url + 'win/optipng.exe', 'win32')
	.dest(path.join(__dirname, '../vendor'))
	.use(process.platform === 'win32' ? 'optipng.exe' : 'optipng')
	.version('>=0.7.5');

'use strict';

var BinWrapper = require('bin-wrapper');
var path = require('path');
var pkg = require('../package.json');
var url = 'https://raw.github.com/imagemin/optipng-bin/v' + pkg.version + '/vendor/';

module.exports = new BinWrapper()
	.src(url + 'osx/optipng', 'darwin')
	.src(url + 'linux/x86/optipng', 'linux', 'x86')
	.src(url + 'linux/x64/optipng', 'linux', 'x64')
	.src(url + 'freebsd/optipng', 'freebsd')
	.src(url + 'sunos/x86/optipng', 'sunos', 'x86')
	.src(url + 'sunos/x64/optipng', 'sunos', 'x64')
	.src(url + 'win/optipng.exe', 'win32')
	.dest(path.join(__dirname, '../vendor'))
	.use(process.platform === 'win32' ? 'optipng.exe' : 'optipng')
	.version('>=0.7.5');

Change version tag to include v


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

var monq = module.exports = {};

monq.Job = require('./job');
monq.Queue = require('./queue');
monq.Worker = require('./worker');

monq.pubsub = mubsub.channel('events');

monq.worker = function(options) {
    options.pubsub || (options.pubsub = monq.pubsub);
    return new monq.Worker(options);
};

monq.queue = function(name) {
    return new monq.Queue(name);
};

monq.subscribe = function(job, callback) {
    return monq.pubsub.subscribe({ 'job._id': job._id }, callback);
};

monq.connect = function(db) {
    mongoose.connect(db);
    mubsub.connect(db);
};

monq.disconnect = function() {
    mongoose.disconnect();
    mubsub.disconnect();
};

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

var monq = module.exports = {};

monq.Job = require('./job');
monq.Queue = require('./queue');
monq.Worker = require('./worker');

monq.pubsub = mubsub.channel('events');

monq.worker = function(options) {
    options.pubsub || (options.pubsub = monq.pubsub);
    return new monq.Worker(options);
};

monq.queue = function(name) {
    return new monq.Queue(name);
};

monq.subscribe = function(job, callback) {
    return monq.pubsub.subscribe({ 'job._id': job._id }, callback);
};

monq.connect = function(db) {
    mongoose.connect(db);
    mubsub.connect(db);
    return monq;
};

monq.disconnect = function() {
    mongoose.disconnect();
    mubsub.disconnect();
};

Allow connect call to be chained


var path = require('path');
var _ = require('underscore')._;

module.exports = function(app, settings) {
  var providers = {};
  for (var p in settings.providers) {
      // TODO :express better
      providers[p] = require('./' + path.join(p, 'index'))(app, settings);
  }
  app.get('/provider', function(req, res) {
      res.send({
          status: true,
          provider: _.keys(settings.providers)
      });
  });
  app.get('/provider/:provider', function(req, res) {
      providers[req.params.provider].objects(function(objects) {
          res.send({
              status: true,
              name: providers[req.params.provider].name,
              datasources: objects
          });
      });
  });
};

var path = require('path');
var _ = require('underscore')._;

module.exports = function(app, settings) {
  var providers = {};
  for (var p in settings.providers) {
      // TODO :express better
      providers[p] = require('./' + path.join(p, 'index'))(app, settings);
  }
  app.get('/provider', function(req, res) {
      res.send({
          status: true,
          provider: _.keys(settings.providers)
      });
  });
  app.get('/provider/:provider', function(req, res) {
      providers[req.params.provider].objects(function(objects) {
          res.send(objects);
      });
  });
};

Send list of objects for backbone compatibility.


var scrapinode = require('./../main.js')();

// Issue with this page similar to https://github.com/tmpvar/jsdom/issues/290
// Works great with cheerio
var url = 'http://www.dell.com/uk/p/xps-15z/pd?oc=n0015z01epp&model_id=xps-15z&';

scrapinode.createScraper(url,'jsdom',function(err,scraper){
   if(err){
    console.log(err);
   }else{
      var title = scraper.get('title');
      var description = scraper.get('description');
      var images = scraper.get('images');
      console.log('IMAGES');
      console.log(images);
      console.log('TITLE:'+title);
      console.log('DESCRIPTION');
      console.log(description);
   }
});

var scrapinode = require('./../main.js')();

// Issue with this page similar to https://github.com/tmpvar/jsdom/issues/290
// Fix https://github.com/tmpvar/jsdom/pull/387
// Works great with cheerio
var url = 'http://www.dell.com/uk/p/xps-15z/pd?oc=n0015z01epp&model_id=xps-15z&';

scrapinode.createScraper(url,'jsdom',function(err,scraper){
   if(err){
    console.log(err);
   }else{
      var title = scraper.get('title');
      var description = scraper.get('description');
      var images = scraper.get('images');
      console.log('IMAGES');
      console.log(images);
      console.log('TITLE:'+title);
      console.log('DESCRIPTION');
      console.log(description);
   }
});

Add link to the pull request that fix the issue.


export * from './filters';
export * from './formatters';
export * from './supports';
export * from './common';
export * from './url';

Fix missing url module bug


var path = require('path')

var projectRoot = path.resolve(__dirname, '../')

module.exports = {
  entry: {
    "vue-typer": path.join(projectRoot, 'src/main.js')
  },
  output: {
    path: path.join(projectRoot, 'dist'),
    filename: '[name].js'
  },
  module: {
    rules: [
      {
        enforce: 'pre',
        test: /\.(js|vue)$/,
        loader: 'eslint-loader',
        options: {
          formatter: require('eslint-friendly-formatter')
        },
        include: projectRoot,
        exclude: /node_modules/
      }
    ]
  }
}

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

var projectRoot = path.resolve(__dirname, '../')

module.exports = {
  entry: {
    "vue-typer": path.join(projectRoot, 'src/main.js')
  },
  output: {
    path: path.join(projectRoot, 'dist'),
    filename: '[name].js'
  },
  module: {
    rules: [
      {
        enforce: 'pre',
        test: /\.(js|vue)$/,
        loader: 'eslint-loader',
        options: {
          formatter: require('eslint-friendly-formatter')
        },
        include: projectRoot,
        exclude: /node_modules/
      }
    ]
  },
  plugins: [
    // Required for vue-loader: http://vuejs.github.io/vue-loader/en/workflow/production.html
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: JSON.stringify(process.env.NODE_ENV)
      }
    })
  ]
}

Define process.env.NODE_ENV for vue-loader, which will be added later


const webpack = require(`webpack`);
const FaviconsWebpackPlugin = require('favicons-webpack-plugin')

exports.modifyWebpackConfig = ({ config }) =>
  config.plugin(`Favicon`, FaviconsWebpackPlugin, ['./src/favicon.png'])

const webpack = require(`webpack`);
const FaviconsWebpackPlugin = require('favicons-webpack-plugin')

exports.modifyWebpackConfig = ({ config }) =>
  config.plugin(`Favicon`, FaviconsWebpackPlugin, [
    {
      logo: './src/favicon.png',
      prefix: 'favicons/'
    }
  ])

Configure favicons to a fixed folder


import { Promise } from 'rsvp';

import { nextTick } from './-utils';

export default function(callback, options = {}) {
  let timeout = 'timeout' in options ? options.timeout : 1000;
  let waitUntilTimedOut = new Error('waitUntil timed out');

  return new Promise(function(resolve, reject) {
    // starting at -10 because the first invocation happens on 0
    // but still increments the time...
    let time = -10;
    function tick() {
      time += 10;
      let value = callback();
      if (value) {
        resolve(value);
      } else if (time < timeout) {
        // using `setTimeout` directly to allow fake timers
        // to intercept
        setTimeout(tick, 10);
      } else {
        reject(waitUntilTimedOut);
      }
    }

    nextTick(tick);
  });
}

import { Promise } from 'rsvp';

import { nextTick } from './-utils';

export default function(callback, options = {}) {
  let timeout = 'timeout' in options ? options.timeout : 1000;
  let waitUntilTimedOut = new Error('waitUntil timed out');

  return new Promise(function(resolve, reject) {
    // starting at -10 because the first invocation happens on 0
    // but still increments the time...
    let time = -10;
    function tick() {
      time += 10;
      let value = callback();
      if (value) {
        resolve(value);
      } else if (time < timeout) {
        // using `setTimeout` directly to allow fake timers
        // to intercept
        nextTick(tick, 10);
      } else {
        reject(waitUntilTimedOut);
      }
    }

    nextTick(tick);
  });
}

Use `nextTick` to avoid time shifting issues.


class CampaignView {
  constructor(){

  }

  getIndex(campaigns) {
    console.log('Campaign View: Get index');
    var campaignHTML = `<h1>Campaign Index<h1>`;

    for(let i = 0; i < campaigns.length; i++) {
      campaignHTML += `<button class='campaign_show' data-id='${campaigns[i].id}'>Campaign ${campaigns[i].name}</button>`;
    }

    campaignHTML += `<button id='campaign_new'>New</button>`;
    return campaignHTML;
  }

  new() {
    return `
New Campaign

This is the new campaign view

            <form name='form_campaign_new'>
            Campaign Name
            <input name='name' id='name'/>

            Description
            <textarea name='description' id='description'>
            </textarea>

            Expiry Date
            <input name='expiry' id='expiry' type='date' />

            Daily Posts
            <input name='dailyPosts' id='dailyPosts' type='number' />

            <button id='campaign_save'>Save</button>
            <button id='campaign_index'>Cancel</button>
            </form>`;
  }

  show(campaign) {
    return `
Show Campaign

This is the show campaign view. ID: ${campaign.id}
`;
  }

  edit(campaign) {
    return `
Edit Campaign

This is the edit campaign view
`;
  }
}

class CampaignView {
  constructor(){

  }

  getIndex(campaigns) {
    console.log('Campaign View: Get index');
    var campaignHTML = `<h1>Campaign Index<h1>`;

    for(let i = 0; i < campaigns.length; i++) {
      campaignHTML += `<button class='campaign_show' data-id='${campaigns[i].id}'>Campaign ${campaigns[i].name}</button>`;
    }

    campaignHTML += `<button id='campaign_new'>New</button>`;
    return campaignHTML;
  }

  new() {
    return `
New Campaign

This is the new campaign view

            <form name='form_campaign_new'>
            Campaign Name
            <input name='name' id='name'/>

            Description
            <textarea name='description' id='description'></textarea>

            Expiry Date
            <input name='expiry' id='expiry' type='date' />

            Daily Posts
            <input name='dailyPosts' id='dailyPosts' type='number' min='0' max='10'/>

            <button id='campaign_save'>Save</button>
            <button id='campaign_index'>Cancel</button>
            </form>`;
  }

  show(campaign) {
    return `
Show Campaign

This is the show campaign view. ID: ${campaign.id}
`;
  }

  edit(campaign) {
    return `
Edit Campaign

This is the edit campaign view
`;
  }
}

Remove whitespace from campaign text area


angular.module('sislegisapp').factory('ReuniaoResource',
		function($resource, BACKEND) {
			return $resource(BACKEND + '/reuniaos/:ReuniaoId', {
				ReuniaoId : '@id'
			}, {
				'queryAll' : {
					method : 'GET',
					isArray : true
				},
				'query' : {
					method : 'GET',
					isArray : false
				},
				'buscarReuniaoPorData' : {
					url : BACKEND + "/reuniaos/findByData",
					method : 'GET',
					isArray : true,
                    transformResponse: function(data){
                        var jsonParse = JSON.parse(data);
                        jsonParse.forEach(function(item, index){
                            if(item.posicionamentoPreliminar==true){
                                jsonParse[index].posicionamento.nome = 'Previamente ' + item.posicionamentoAtual.posicionamento.nome;
                            }
                        });
                        return jsonParse;
                    }
				},
				'update' : {
					method : 'PUT'
				}
			});
		});

angular.module('sislegisapp').factory('ReuniaoResource',
		function($resource, BACKEND) {
			return $resource(BACKEND + '/reuniaos/:ReuniaoId', {
				ReuniaoId : '@id'
			}, {
				'queryAll' : {
					method : 'GET',
					isArray : true
				},
				'query' : {
					method : 'GET',
					isArray : false
				},
				'buscarReuniaoPorData' : {
					url : BACKEND + "/reuniaos/findByData",
					method : 'GET',
					isArray : true,
                    transformResponse: function(data){
                        var jsonParse = JSON.parse(data);
                        jsonParse.forEach(function(item, index){
                            if(item.posicionamentoPreliminar==true){
                                jsonParse[index].posicionamentoAtual.nome = 'Previamente ' + item.posicionamentoAtual.posicionamento.nome;
                            }
                        });
                        return jsonParse;
                    }
				},
				'update' : {
					method : 'PUT'
				}
			});
		});

Fix para modelo de posicioanmento autal


'use strict';

exports.for = function (n) {
  var prime_factors = [];
  var possible_factor = 2;
  while (possible_factor * possible_factor <= n) {
    while (n % possible_factor === 0) {
      prime_factors.push(possible_factor);
      n /= possible_factor;
    }
    possible_factor += 1;
  }
  if (n > 1) { prime_factors.push(n); }
  return prime_factors;
};

'use strict';

exports.for = function (n) {
  var primeFactors = [];
  var possibleFactor = 2;
  var number = n;
  while (possibleFactor * possibleFactor <= number) {
    while (number % possibleFactor === 0) {
      primeFactors.push(possibleFactor);
      number /= possibleFactor;
    }
    possibleFactor += 1;
  }
  if (number > 1) { primeFactors.push(number); }
  return primeFactors;
};

Fix eslint errors in prime-factors


"use strict";

var ace = require('brace');
require('brace/theme/tomorrow');
require('brace/mode/javascript');

var React = require('react/addons');

var IdeComponent = React.createClass({
  editor: null,
  componentDidMount: function () {
    this.editor = ace.edit(this.refs.ide.getDOMNode());
    this.editor.setTheme('ace/theme/tomorrow');

    var session = this.editor.getSession();
    session.setMode('ace/mode/javascript');
    session.setTabSize(2);
    session.setUseSoftTabs(true);
    session.on('change', this.onChange);
  },
  componentDidUpdate: function () {
    this.editor.setValue(this.props.code);
  },
  render: function () {
    return (
      <div ref='ide' className='ide'>
      </div>
    );
  },
  onChange: function () {
    this.props.onChange(this.editor.getValue());
  }
});

module.exports = IdeComponent;

"use strict";

var ace = require('brace');
require('brace/theme/tomorrow');
require('brace/mode/javascript');

var React = require('react/addons');

var IdeComponent = React.createClass({
  editor: null,
  componentDidMount: function () {
    this.editor = ace.edit(this.refs.ide.getDOMNode());
    this.editor.setTheme('ace/theme/tomorrow');

    var session = this.editor.getSession();
    session.setMode('ace/mode/javascript');
    session.setTabSize(2);
    session.setUseSoftTabs(true);
    session.on('change', this.onChange);
  },
  render: function () {
    return
{this.props.code}
;
  },
  onChange: function () {
    this.props.onChange(this.editor.getValue());
  }
});

module.exports = IdeComponent;

Fix bug in prefilling IDE.


'use strict';

angular.module('ngClipboard', []).
  value('ZeroClipboardConfig', {
    path: '//cdnjs.cloudflare.com/ajax/libs/zeroclipboard/1.2.3/ZeroClipboard.swf'
  }).
  directive('clipCopy', ['$window', 'ZeroClipboardConfig', function ($window, ZeroClipboardConfig) {
    return {
      scope: {
        clipCopy: '&',
        clipClick: '&'
      },
      restrict: 'A',
      link: function (scope, element, attrs) {
        // Create the clip object
        var clip = new ZeroClipboard( element, {
          moviePath: ZeroClipboardConfig.path,
          trustedDomains: ['*'],
          allowScriptAccess: "always"
        });

        clip.on( 'mousedown', function(client) {
          client.setText(scope.$eval(scope.clipCopy));
          if (angular.isDefined(attrs.clipClick)) {
            scope.$apply(scope.clipClick);
          }
        });
      }
    }
  }]);

'use strict';

angular.module('ngClipboard', []).
  value('ZeroClipboardConfig', {
    path: '//cdnjs.cloudflare.com/ajax/libs/zeroclipboard/1.2.3/ZeroClipboard.swf'
  }).
  directive('clipCopy', ['$window', 'ZeroClipboardConfig', function ($window, ZeroClipboardConfig) {
    return {
      scope: {
        clipCopy: '&',
        clipClick: '&'
      },
      restrict: 'A',
      link: function (scope, element, attrs) {
        // Create the clip object
        var clip = new ZeroClipboard( element, {
          moviePath: ZeroClipboardConfig.path,
          trustedDomains: ['*'],
          allowScriptAccess: "always"
        });

        var onMousedown = function (client) {
          client.setText(scope.$eval(scope.clipCopy));
          if (angular.isDefined(attrs.clipClick)) {
            scope.$apply(scope.clipClick);
          }
        };
        clip.on('mousedown', onMousedown);

        scope.$on('$destroy', function() {
          clip.off('mousedown', onMousedown);
          clip.unglue(element);
        });
      }
    }
  }]);

Clean up nicely upon $destruction.


var p5 = require('p5');

console.log(pulsarConfig);

var sketch = function (p) {

  var Receiver = require('./Receiver.js');
  var receiver = new Receiver();

  var Processor = require('./Processor.js');
  var processor = new Processor();

  var DrawingManager = require('./DrawingManager.js');
  var dM = new DrawingManager(p);

  p.setup = function() {
    p.frameRate(30);
    receiver.connect();

    receiver.on('received', function(data) {
      console.log("Pulsar: received: " + data);

      var drawing = processor.createDrawing(data);

      dM.add(drawing);
      // give to drawing manager
    })

    p.createCanvas(p.windowWidth, p.windowHeight);
  }

  p.draw = function() {
    p.noStroke();
    p.background(0);

    dM.drawAll();

    p.textSize(15);
    p.fill(175);
    var verWidth = p.textWidth("PULSAR - v0.0.1");
    p.text("PULSAR - v0.0.1", p.windowWidth - verWidth - 10, p.windowHeight - 10);
  }

  p.windowResized = function() {
    p.resizeCanvas(p.windowWidth, p.windowHeight);
  }
}

var myp5 = new p5(sketch);

var p5 = require('p5');

var pulsar = {};
pulsar.config = pulsarConfig;
pulsarConfig = undefined;

pulsar.sketch = function (p) {

  var Receiver = require('./Receiver.js');
  var receiver = new Receiver();

  var Processor = require('./Processor.js');
  var processor = new Processor();

  var DrawingManager = require('./DrawingManager.js');
  var dM = new DrawingManager(p);

  p.setup = function() {
    p.frameRate(30);
    receiver.connect();

    receiver.on('received', function(data) {
      console.log("Pulsar: received: " + data);

      var drawing = processor.createDrawing(data);

      dM.add(drawing);
      // give to drawing manager
    })

    p.createCanvas(p.windowWidth, p.windowHeight);
  }

  p.draw = function() {
    p.noStroke();
    p.background(0);

    dM.drawAll();

    p.textSize(15);
    p.fill(175);
    var verWidth = p.textWidth("PULSAR - v0.0.1");
    p.text("PULSAR - v0.0.1", p.windowWidth - verWidth - 10, p.windowHeight - 10);
  }

  p.windowResized = function() {
    p.resizeCanvas(p.windowWidth, p.windowHeight);
  }
}

new p5(pulsar.sketch);

Clean up variables a bit


import Chance from 'chance'
import { VALUE_DEFAULT_STRING_LENGTH } from './constants'

const chanceInstance = new Chance()

export const randomByte = ({chance = chanceInstance}) => {
  return chance.natural({max: 255}).toString()
}

export const randomShort = ({chance = chanceInstance}) => {
  return chance.natural({max: 65535}).toString()
}

export const randomInt = ({chance = chanceInstance}) => {
  return chance.natural({max: 4294967295}).toString()
}

export const randomLong = ({chance = chanceInstance}) => {
  return chance.natural().toString()
}

export const randomGuid = ({chance = chanceInstance}) => {
  return chance.guid()
}

export const randomString = ({chance = chanceInstance, inputValue = VALUE_DEFAULT_STRING_LENGTH}) => {
  return chance.word({length: inputValue})
}

export const randomName = ({chance = chanceInstance}) => {
  return chance.name()
}

export const randomStreetAddress = ({chance = chanceInstance}) => {
  return chance.address()
}

export const randomCity = ({chance = chanceInstance}) => {
  return chance.city()
}

export const randomPhoneNumber = ({chance = chanceInstance}) => {
  return chance.phone()
}

export const randomEmail = ({chance = chanceInstance}) => {
  return chance.email()
}

import Chance from 'chance'
import { isValid } from './validations'
import { VALUE_DEFAULT_STRING_LENGTH } from './constants'

let chanceInstance = new Chance()

export const resetSeed = (seed) => {
  chanceInstance = isValid(seed)
    ? new Chance(seed)
    : new Chance()
}

export const randomByte = ({chance = chanceInstance}) => {
  return chance.natural({max: 255}).toString()
}

export const randomShort = ({chance = chanceInstance}) => {
  return chance.natural({max: 65535}).toString()
}

export const randomInt = ({chance = chanceInstance}) => {
  return chance.natural({max: 4294967295}).toString()
}

export const randomLong = ({chance = chanceInstance}) => {
  return chance.natural().toString()
}

export const randomGuid = ({chance = chanceInstance}) => {
  return chance.guid()
}

export const randomString = ({chance = chanceInstance, inputValue = VALUE_DEFAULT_STRING_LENGTH}) => {
  return chance.word({length: inputValue})
}

export const randomName = ({chance = chanceInstance}) => {
  return chance.name()
}

export const randomStreetAddress = ({chance = chanceInstance}) => {
  return chance.address()
}

export const randomCity = ({chance = chanceInstance}) => {
  return chance.city()
}

export const randomPhoneNumber = ({chance = chanceInstance}) => {
  return chance.phone()
}

export const randomEmail = ({chance = chanceInstance}) => {
  return chance.email()
}

Add new function to reset seed


var path = require("path");

var outputDirectory = path.resolve("./output");
var libsDirectory = path.resolve("./libs");
var tempDirectory = path.resolve("./build_temp");

module.exports = {
  particle: {
    platform: "photon", // See https://github.com/spark/firmware/blob/develop/docs/build.md#platform-nameids
    targetName: "weather-thingy-particle", // See https://github.com/spark/firmware/blob/develop/docs/build.md#compiling-an-application-outside-the-firmware-source
    firmwareDirectory: path.resolve(libsDirectory + "/particle/firmware"),
    firmwareRepository: "git@github.com:spark/firmware.git",
    firmwareVersion: "v0.4.7"
  },
  build: {
    sources: {
      application: path.resolve("./src"),
      tests: path.resolve("./tests")
    },
    output: {
      baseDirectory: outputDirectory,
      firmware: outputDirectory + "/firmware",
      tests: outputDirectory + "/tests"
    },
    temp: {
      baseDirectory: tempDirectory,
      testBuildFiles: tempDirectory + "/tests/build"
    }
  },
  lint: {
    cpp: {
      cppcheckOptions: "--enable=all --inline-suppr" // --check-config is quite handy for making sure that everything is configured correctly but is very noisy
    }
  }
};

var path = require("path");

var outputDirectory = path.resolve("./output");
var libsDirectory = path.resolve("./libs");
var tempDirectory = path.resolve("./build_temp");

module.exports = {
  particle: {
    platform: "photon", // See https://github.com/spark/firmware/blob/develop/docs/build.md#platform-nameids
    targetName: "weather-thingy-particle", // See https://github.com/spark/firmware/blob/develop/docs/build.md#compiling-an-application-outside-the-firmware-source
    firmwareDirectory: path.resolve(libsDirectory + "/particle/firmware"),
    firmwareRepository: "https://github.com/spark/firmware.git",
    firmwareVersion: "v0.4.7"
  },
  build: {
    sources: {
      application: path.resolve("./src"),
      tests: path.resolve("./tests")
    },
    output: {
      baseDirectory: outputDirectory,
      firmware: outputDirectory + "/firmware",
      tests: outputDirectory + "/tests"
    },
    temp: {
      baseDirectory: tempDirectory,
      testBuildFiles: tempDirectory + "/tests/build"
    }
  },
  lint: {
    cpp: {
      cppcheckOptions: "--enable=all --inline-suppr" // --check-config is quite handy for making sure that everything is configured correctly but is very noisy
    }
  }
};

Use HTTPS rather than SSH to clone Particle firmware repository.


const path = require(`path`);

const sass2css = require(`../lib/sass2css.js`);

module.exports = (packageName) => {
  const packagePath = path.join(process.cwd(), `avalanche`, `packages`, packageName);
  const inputFile = path.join(packagePath, `test`, `test.scss`);
  const outputFile = path.join(process.cwd(), `dist`, `packages`, packageName, `css`, `index.css`);

  sass2css(inputFile, outputFile, { cwd: packagePath });
};

const path = require(`path`);

const sass2css = require(`../lib/sass2css.js`);

module.exports = (packageName) => {
  const packagePath = path.join(process.cwd(), `avalanche`, `packages`, packageName);
  const inputFile = path.join(packagePath, `scss`, `index.scss`);
  const outputFile = path.join(process.cwd(), `dist`, `packages`, packageName, `css`, `index.css`);

  sass2css(inputFile, outputFile, { cwd: packagePath });
};

Load the main scss file from packages to generate the styles for the demo code.


const toggleValue = (currentValue, value1, value2) => {
  if (currentValue === value1) {
    return value2;
  }

  return value1;
}

export { toggleValue as default };

const toggleValue = (currentValue, value1, value2) => {
  if (currentValue === value1) {
    return value2;
  }

  return value1;
};

export { toggleValue as default };

Add semi-colon at end of function


var SimpleEmail = require('./SimpleNEParser');

SimpleEmail.fromPath('data.txt', function(email) {
//  console.log(email);
});

SimpleEmail.fromString('nowai from string', function(email) {
//  console.log(email);
});

var SimpleEmail = require('../lib/SimpleNEParser');

SimpleEmail.fromPath(__dirname + '/data.txt', function(email) {
//  console.log(email);
});

SimpleEmail.fromString('nowai from string', function(email) {
//  console.log(email);
});

Add actual directory path for data.txt.


#!/usr/bin/env node

var amqp = require('amqplib/callback_api');

amqp.connect('amqp://localhost', function(err, conn) {
  conn.createChannel(function(err, ch) {
    var q = 'hello';
    var msg = 'Hello World!';

    ch.assertQueue(q, {durable: false});
    ch.sendToQueue(q, Buffer.from(msg));
    console.log(" [x] Sent %s", msg);
  });
  setTimeout(function() { conn.close(); process.exit(0) }, 500);
});

#!/usr/bin/env node

var amqp = require('amqplib/callback_api');

amqp.connect('amqp://localhost', function(err, conn) {
  conn.createChannel(function(err, ch) {
    var q = 'hello';
    var msg = 'Hello World!';

    ch.assertQueue(q, {durable: false});
    ch.sendToQueue(q, new Buffer(msg));
    console.log(" [x] Sent %s", msg);
  });
  setTimeout(function() { conn.close(); process.exit(0) }, 500);
});

Revert "Use `Buffer.from` in place of `new Buffer`"


var Trie = require('../app/trie');

describe('Trie', function() {
  var trie;

  beforeEach(function() {
    trie = new Trie();
  });

  it('should be an object', function() {
    expect(trie).to.be.ok;
  });

  it('should have a root', function() {
    expect(trie.root).to.be.ok;
  });

  it('should have add method', function() {
    expect(trie.add).to.be.an.instanceof(Function);
  });

  it('should have search method', function() {
    expect(trie.search).to.be.an.instanceof(Function);
  });

  it('should have find method', function() {
    expect(trie.find).to.be.an.instanceof(Function);
  });
});

var Trie = require('../app/trie');

describe('Trie', function() {
  var trie;

  beforeEach(function() {
    trie = new Trie();
  });

  it('should be an object', function() {
    expect(trie).to.be.ok;
  });

  it('should have a root', function() {
    expect(trie.root).to.be.ok;
  });

  it('should have add method', function() {
    expect(trie.add).to.be.an.instanceof(Function);
  });

  it('should add string to trie', function() {
    expect(trie.add('test')).to.be.undefined;
  });

  it('should have search method', function() {
    expect(trie.search).to.be.an.instanceof(Function);
  });

  it('should have find method', function() {
    expect(trie.find).to.be.an.instanceof(Function);
  });
});

Add test for add string method return value


(function() {
	var CustomersController = function($scope) {
		$scope.sortBy = 'name';
  		$scope.reverse = false;
  		$scope.customers = [{name:'John', city:'London', joined:'2014-12-02', orderTotal:212.5},
			{name:'Paul', city:'Liverpool', joined:'2014-11-02', orderTotal:312.1},
			{name:'George', city:'Glasgow', joined:'2014-10-02', orderTotal:435.99},
			{name:'Leo', city:'Albuquerque', joined:'2014-01-02', orderTotal:415.99},
			{name:'Ringo', city:'Manchester', joined:'2014-11-12', orderTotal:111}];
  		$scope.doSort = function (propName) {
			$scope.sortBy = propName;
			$scope.reverse = !$scope.reverse
  		};
	};
	angular.module('myApp').controller('CustomersController', CustomersController);
}());

(function() {
	var CustomersController = function($scope) {
		$scope.sortBy = 'name';
  		$scope.reverse = false;
  		$scope.customers = [{name:'John', city:'London', joined:'2014-12-02', orderTotal:212.5},
			{name:'Paul', city:'Liverpool', joined:'2014-11-02', orderTotal:312.1},
			{name:'George', city:'Glasgow', joined:'2014-10-02', orderTotal:435.99},
			{name:'Leo', city:'Albuquerque', joined:'2014-01-02', orderTotal:415.99},
			{name:'Ringo', city:'Manchester', joined:'2014-11-12', orderTotal:111}];
  		$scope.doSort = function (propName) {
			$scope.sortBy = propName;
			$scope.reverse = !$scope.reverse
  		};
	};
	CustomersController.$inject = ['$scope'];
	angular.module('myApp').controller('CustomersController', CustomersController);
}());

Add $inject -- to prevent minifiers


import app from './server';
import http from 'http';

const server = http.createServer(app);

let currentApp = app;

server.listen(process.env.PORT || 3000, error => {
  if (error) {
    console.log(error);
  }

  console.log('🚀 started');
});

if (module.hot) {
  console.log('✅  Server-side HMR Enabled!');

  module.hot.accept('./server', () => {
    console.log('🔁  HMR Reloading `./server`...');
    server.removeListener('request', currentApp);
    const newApp = require('./server').default;
    server.on('request', newApp);
    currentApp = newApp;
  });
}

import app from './server';
import http from 'http';

const server = http.createServer(app);

let currentApp = app;

server.listen(process.env.PORT || 3000, error => {
  if (error) {
    console.log(error);
  }

  console.log('🚀 started');
});

if (module.hot) {
  console.log('✅  Server-side HMR Enabled!');

  const noErrors = () => {
    try {
      require('./server').default;
    } catch (error) {
      console.error(error);
      return false;
    }
    return true;
  };

  module.hot.accept('./server', () => {
    if (noErrors()) {
      console.log('🔁  HMR Reloading `./server`...');
      server.removeListener('request', currentApp);
      const newApp = require('./server').default;
      server.on('request', newApp);
      currentApp = newApp;
    }
  });
}

Fix for '[HMR] You need to restart the application!' on server sided err


(function() {
  if (window.location.hostname.indexOf('localhost') > -1) {
    return;
  }

  var script = document.createElement('script');
  window.counter = 'https://chrisdeluca.goatcounter.com/count'
  script.async = 1;
  script.src = '//static.goatcounter.com/count.min.js';

  var ins = document.getElementsByTagName('script')[0];
  ins.parentNode.insertBefore(script, ins)
})();

(function() {
  if (window.location.hostname.indexOf('localhost') > -1) {
    return;
  }

  var script = document.createElement('script');
  window.counter = 'https://chrisdeluca.goatcounter.com/count'
  script.async = 1;
  script.src = 'https://static.goatcounter.com/count.min.js';

  var ins = document.getElementsByTagName('script')[0];
  ins.parentNode.insertBefore(script, ins)
})();

Use always secure tracking script


RocketChat.cache.Rooms.hasMany('Subscriptions', {
	field: 'usernames',
	link: {
		local: '_id',
		remote: 'rid',
		transform(room, subscription) {
			return subscription.u.username;
		},
		remove(arr, subscription) {
			if (arr.indexOf(subscription.u.username) > -1) {
				arr.splice(arr.indexOf(subscription.u.username), 1);
			}
		}
	}
});

RocketChat.cache.Subscriptions.hasOne('Rooms', {
	field: '_room',
	link: {
		local: 'rid',
		remote: '_id'
	}
});

RocketChat.cache.Users.load();
RocketChat.cache.Rooms.load();
RocketChat.cache.Subscriptions.load();
RocketChat.cache.Settings.load();

RocketChat.cache.Users.addDynamicView('highlights').applyFind({
	'settings.preferences.highlights': {$size: {$gt: 0}}
});

RocketChat.cache.Subscriptions.addDynamicView('notifications').applyFind({
	$or: [
		{desktopNotifications: {$in: ['all', 'nothing']}},
		{mobilePushNotifications: {$in: ['all', 'nothing']}}
	]
});

RocketChat.cache.Rooms.hasMany('Subscriptions', {
	field: 'usernames',
	link: {
		local: '_id',
		remote: 'rid',
		transform(room, subscription) {
			return subscription.u.username;
		},
		remove(arr, subscription) {
			if (arr.indexOf(subscription.u.username) > -1) {
				arr.splice(arr.indexOf(subscription.u.username), 1);
			}
		}
	}
});

RocketChat.cache.Subscriptions.hasOne('Rooms', {
	field: '_room',
	link: {
		local: 'rid',
		remote: '_id'
	}
});

RocketChat.cache.Subscriptions.hasOne('Users', {
	field: '_user',
	link: {
		local: 'u._id',
		remote: '_id'
	}
});

RocketChat.cache.Users.load();
RocketChat.cache.Rooms.load();
RocketChat.cache.Subscriptions.load();
RocketChat.cache.Settings.load();

RocketChat.cache.Users.addDynamicView('highlights').applyFind({
	'settings.preferences.highlights': {$size: {$gt: 0}}
});

RocketChat.cache.Subscriptions.addDynamicView('notifications').applyFind({
	$or: [
		{desktopNotifications: {$in: ['all', 'nothing']}},
		{mobilePushNotifications: {$in: ['all', 'nothing']}}
	]
});

Add join between Subscroptions and Users


var nocache = require('..')

var assert = require('assert')
var connect = require('connect')
var request = require('supertest')

describe('nocache', function () {
  it('sets headers properly', function (done) {
    var app = connect()
    app.use(function (req, res, next) {
      res.setHeader('ETag', 'abc123')
      next()
    })
    app.use(nocache())
    app.use(function (req, res) {
      res.end('Hello world!')
    })

    request(app).get('/')
    .expect('Surrogate-Control', 'no-store')
    .expect('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate')
    .expect('Pragma', 'no-cache')
    .expect('Expires', '0')
    .expect('ETag', 'abc123')
    .expect('Hello world!')
    .end(done)
  })

  it('names its function and middleware', function () {
    assert.equal(nocache.name, 'nocache')
    assert.equal(nocache().name, 'nocache')
  })
})

var nocache = require('..')

var assert = require('assert')
var connect = require('connect')
var request = require('supertest')

describe('nocache', function () {
  it('sets headers properly', function () {
    var app = connect()
    app.use(function (req, res, next) {
      res.setHeader('ETag', 'abc123')
      next()
    })
    app.use(nocache())
    app.use(function (req, res) {
      res.end('Hello world!')
    })

    return request(app).get('/')
      .expect('Surrogate-Control', 'no-store')
      .expect('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate')
      .expect('Pragma', 'no-cache')
      .expect('Expires', '0')
      .expect('ETag', 'abc123')
      .expect('Hello world!')
  })

  it('names its function and middleware', function () {
    assert.equal(nocache.name, 'nocache')
    assert.equal(nocache().name, 'nocache')
  })
})

Use promises instead of callbacks in test


import React, { Component, PropTypes } from 'react';
import { ContentLayoutEngine, BlockTypeMap } from '../index';

export default class SectionLayoutRenderer extends Component {
  static renderBlocks(blocks, blockMap) {
    if (!blocks && !blocks.length) {
      return null;
    }

    // Merge user supplied content blocks with default set.
    let mergedBlockMap = BlockTypeMap;
    if (blockMap) {
      mergedBlockMap = {
        ...BlockTypeMap,
        ...blockMap
      }
    }

    return blocks.map((block, index) => { // eslint-disable-line arrow-body-style
      if (!block.blockType) {
        return null;
      }
      return (!block.edit) ? React.cloneElement(
        mergedBlockMap[block.blockType].element,
        {
          ...block,
          key: `block-${index}`,
        },
      ) : undefined;
    });
  }

  render() {
    const { section, blockMap, ...rest } = this.props;

    return (
      <ContentLayoutEngine
        {...rest}
        layout={section.layout}
        blocks={section.contentBlocks}
      >
        {SectionLayoutRenderer.renderBlocks(section.contentBlocks, blockMap)}
      </ContentLayoutEngine>
    );
  }
}

SectionLayoutRenderer.propTypes = {
  section: PropTypes.shape({
    contentBlocks: PropTypes.arrayOf(
      PropTypes.shape({
        blockType: PropTypes.string.isRequired,
        content: PropTypes.string,
        id: PropTypes.string.isRequired,
      }),
    ).isRequired,
    layout: PropTypes.arrayOf(
      PropTypes.shape({
        name: PropTypes.string,
        value: PropTypes.string,
      }),
    ).isRequired,
  }),
  blockMap: PropTypes.array
};

import React, { Component, PropTypes } from 'react';
import { ContentLayoutEngine, BlockTypeMap } from '../index';

export default class SectionLayoutRenderer extends Component {
  static renderBlocks(blocks, blockMap) {
    if (!blocks && !blocks.length) {
      return null;
    }

    // Merge user supplied content blocks with default set.
    let mergedBlockMap = BlockTypeMap;
    if (blockMap) {
      mergedBlockMap = {
        ...BlockTypeMap,
        ...blockMap
      }
    }

    return blocks.map((block, index) => { // eslint-disable-line arrow-body-style
      if (!block.blockType) {
        return null;
      }
      return (!block.edit) ? React.cloneElement(
        mergedBlockMap[block.blockType].element,
        {
          ...block,
          key: `block-${index}`,
        },
      ) : undefined;
    });
  }

  render() {
    const { section, blockMap, ...rest } = this.props;

    return (
      <ContentLayoutEngine
        {...rest}
        layout={section.layout}
        blocks={section.contentBlocks}
      >
        {SectionLayoutRenderer.renderBlocks(section.contentBlocks, blockMap)}
      </ContentLayoutEngine>
    );
  }
}

SectionLayoutRenderer.propTypes = {
  section: PropTypes.shape({
    contentBlocks: PropTypes.arrayOf(
      PropTypes.shape({
        blockType: PropTypes.string.isRequired,
        content: PropTypes.string,
        id: PropTypes.string.isRequired,
      }),
    ).isRequired,
    layout: PropTypes.arrayOf(
      PropTypes.shape({
        name: PropTypes.string,
        value: PropTypes.string,
      }),
    ).isRequired,
  }),
  blockMap: PropTypes.object
};

Fix SectionLayoutRenderer blockMap prop type.


import { omit, pick } from 'lodash/object'
import { find, reduce } from 'lodash/collection'

/**
 * Default transformer methods for each kind of entity.
 * For most cases these just remove information that is specific to the content
 * existing in a space (date created, version, etc), which the new space will
 * generate by itself.
 *
 * In the case of assets it also changes the asset url to the upload property
 * as the whole upload process needs to be followed again.
 */

export function contentTypes (contentType) {
  const transformedContentType = omit(contentType, 'sys')
  transformedContentType.sys = pick(contentType.sys, 'id')
  return transformedContentType
}

export function entries (entry) {
  const transformedEntry = omit(entry, 'sys')
  transformedEntry.sys = pick(entry.sys, 'id')
  return transformedEntry
}

export function assets (asset) {
  const transformedAsset = omit(asset, 'sys')
  transformedAsset.sys = pick(asset.sys, 'id')
  transformedAsset.fields = pick(asset.fields, 'title', 'description')
  transformedAsset.fields.file = reduce(
    asset.fields.file,
    (newFile, file, locale) => {
      newFile[locale] = omit(file, 'url', 'details')
      newFile[locale].upload = 'http:' + file.url
      return newFile
    },
    {}
  )
  return transformedAsset
}

export function locales (locale, destinationLocales) {
  const transformedLocale = pick(locale, 'code', 'name', 'contentManagementApi', 'contentDeliveryApi')
  const destinationLocale = find(destinationLocales, {code: locale.code})
  if (destinationLocale) {
    transformedLocale.sys = pick(destinationLocale.sys, 'id')
  }

  return transformedLocale
}

import { omit, pick } from 'lodash/object'
import { find, reduce } from 'lodash/collection'

/**
 * Default transformer methods for each kind of entity.
 *
 * In the case of assets it also changes the asset url to the upload property
 * as the whole upload process needs to be followed again.
 */

export function contentTypes (contentType) {
  return contentType
}

export function entries (entry) {
  return entry
}

export function assets (asset) {
  asset.fields = pick(asset.fields, 'title', 'description')
  asset.fields.file = reduce(
    asset.fields.file,
    (newFile, file, locale) => {
      newFile[locale] = omit(file, 'url', 'details')
      newFile[locale].upload = 'http:' + file.url
      return newFile
    },
    {}
  )
  return asset
}

export function locales (locale, destinationLocales) {
  const transformedLocale = pick(locale, 'code', 'name', 'contentManagementApi', 'contentDeliveryApi', 'fallback_code', 'optional')
  const destinationLocale = find(destinationLocales, {code: locale.code})
  if (destinationLocale) {
    transformedLocale.sys = pick(destinationLocale.sys, 'id')
  }

  return transformedLocale
}

Remove redundant transformations and fix locale transformations


/**
 * ColonelKurtz Example
 */

import './example.scss'
import ColonelKurtz from '../src/Colonel'
import MediumBlock from '../addons/medium'
import HtmlEmbedBlock from '../addons/html-embed'
import ImageBlock from '../addons/image'
import YouTubeBlock from '../addons/youtube'
import SectionBlock from './blockTypes/Section'

const blockTypes = [
  {
    id: 'section',
    label: 'Section',
    component: SectionBlock,
    types: ['child-text', 'image', 'youtube', 'section'],
    maxChildren: 3
  },
  {
    id: 'medium',
    label: 'Medium Editor',
    component: MediumBlock,
    group: 'Rich Text'
  },
  {
    id: 'embed',
    label: 'Embed',
    component: HtmlEmbedBlock
  },
  {
    id: 'child-text',
    label: 'Child Text',
    component: MediumBlock,
    root: false
  },
  {
    id: 'image',
    label: 'Image',
    group: 'Media',
    component: ImageBlock
  },
  {
    id: 'youtube',
    label: 'YouTube',
    group: 'Media',
    component: YouTubeBlock
  }
]

let editor = new ColonelKurtz({
  el: document.getElementById('app'),
  blockTypes: blockTypes,
  maxChildren: 5,
  maxDepth: 3
})

editor.start()

/**
 * ColonelKurtz Example
 */

import './example.scss'
import ColonelKurtz from '../src/Colonel'
import MediumBlock from '../addons/medium'
import HtmlEmbedBlock from '../addons/html-embed'
import ImageBlock from '../addons/image'
import YouTubeBlock from '../addons/youtube'
import SectionBlock from './blockTypes/Section'

const blockTypes = [
  {
    id: 'section',
    label: 'Section',
    component: SectionBlock,
    types: ['child-text', 'image', 'youtube'],
    maxChildren: 3
  },
  {
    id: 'medium',
    label: 'Medium Editor',
    component: MediumBlock,
    group: 'Rich Text'
  },
  {
    id: 'embed',
    label: 'Embed',
    component: HtmlEmbedBlock
  },
  {
    id: 'child-text',
    label: 'Child Text',
    component: MediumBlock,
    root: false
  },
  {
    id: 'image',
    label: 'Image',
    group: 'Media',
    component: ImageBlock
  },
  {
    id: 'youtube',
    label: 'YouTube',
    group: 'Media',
    component: YouTubeBlock
  }
]

let editor = new ColonelKurtz({
  el: document.getElementById('app'),
  blockTypes: blockTypes,
  maxChildren: 5,
  maxDepth: 3
})

editor.start()

Remove section from child of section


import React from 'react';
import {
  BrowserRouter as Router,
  Route,
  Switch
} from 'react-router-dom';
import firebase from 'firebase';
import { NavigationBar } from '../NavigationBar';
import { PageHome } from '../PageHome';
import { PageLogin } from '../PageLogin';
import { NoRouteMatch } from '../NoRouteMatch';

class PageRouter extends React.Component {
    componentDidMount() {
        firebase.auth().onAuthStateChanged( user => {
            if ( user ) {
                //
            } else {
                //
            }
        });
    }
    render() {
        return (
            <Router>
                <div>
                    <NavigationBar />

                    <Switch>
                        <Route exact path="/" component={PageHome}/>
                        <Route path="/login" component={PageLogin}/>
                        <Route component={NoRouteMatch}/>
                    </Switch>
                </div>
            </Router>
        );
    }
}

export { PageRouter };

export { PageRouter } from './PageRouter.js';
export { SecuredRoute } from './SecuredRoute.js';
export { UnsecuredRoute } from './UnsecuredRoute.js';

Update to PageRouter export components file


import React from 'react';
import { shallow } from 'enzyme';
import Section from './section';

describe('Section', () => {
  let wrapper, children;

  beforeEach(() => {
    wrapper = shallow(

This is some content

    );
  });

  it('renders with main and custom classes', () => {
    expect(wrapper.find('.carbon-section')).toBeTruthy()
    expect(wrapper.find('.my__custom-class')).toBeTruthy()
  });

  it('renders a title', () => {
    let title = wrapper.find('.carbon-section__title')
    expect(title.text()).toEqual('My Section Title')
  });

  it('renders the children content', () => {
    expect(wrapper.contains(
This is some content
)).toBeTruthy();
  });
});

import React from 'react';
import { shallow } from 'enzyme';
import Section from './section';

describe('Section', () => {
  let wrapper, children;

  beforeEach(() => {
    wrapper = shallow(

This is some content

    );
  });

  it('renders with main and custom classes', () => {
    expect(wrapper.find('.carbon-section')).toBeTruthy()
    expect(wrapper.find('.my-custom-class')).toBeTruthy()
  });

  it('renders a title', () => {
    let title = wrapper.find('.carbon-section__title')
    expect(title.text()).toEqual('My Section Title')
  });

  it('renders the children content', () => {
    expect(wrapper.contains(
This is some content
)).toBeTruthy();
  });
});

Correct BEM class in spec


'use strict';

var config = require('../config');
var Backbone = require('backbone');
var User = require('./user');

var World = module.exports = Backbone.Model.extend({
  initialize: function () {
    this.users = new User.Collection();
    console.log(this.users);
  },
  // control flow
  step: function () {
    var now = Date.now();
    var dt = (now - this.lastStep) / 1000;
    this.lastStep = now;
    this.users.invoke('step', this);
    // this.users.checkCollisions();
    this.trigger('step', this.users.invoke('toFrame', dt));
  },
  start: function () {
    if (this.running) {
      console.error('game already running!');
    } else {
      this.lastStep = Date.now();
      this.running = setInterval(this.step.bind(this), 1000 / config.world.fps);
      console.log('game started!');
    }
  },
  stop: function () {
    if (!this.running) {
      console.error('game not currently running!');
    } else {
      console.log('game stopped!');
      clearInterval(this.running);
    }
  }
});

World.Collection = Backbone.Collection.extend({
  model: World
});

'use strict';

var config = require('../config');
var Backbone = require('backbone');
var User = require('./user');

var World = module.exports = Backbone.Model.extend({
  initialize: function () {
    this.users = new User.Collection();
    console.log(this.users);
  },
  // control flow
  step: function () {
    var now = Date.now();
    var dt = (now - this.lastStep) / 1000;
    this.lastStep = now;
    this.users.invoke('step', dt);
    // this.users.checkCollisions();
    this.trigger('step', this.users.invoke('toFrame'));
  },
  start: function () {
    if (this.running) {
      console.error('game already running!');
    } else {
      this.lastStep = Date.now();
      this.running = setInterval(this.step.bind(this), 1000 / config.world.fps);
      console.log('game started!');
    }
  },
  stop: function () {
    if (!this.running) {
      console.error('game not currently running!');
    } else {
      console.log('game stopped!');
      clearInterval(this.running);
    }
  }
});

World.Collection = Backbone.Collection.extend({
  model: World
});

Put dt in the wrong spot!


define([
	'underscore',
	'controller'
], function (_, Controller) {

	var AccountController = Controller.extend({

		handers: {
			'account:add' : 'createAccount'
		},

		initialize: function (opts) {
			this.collection.on('change:connected', this.accountConnected.bind(this));
		},

		createAccount: function (options) {
			return this.collection.create(arguments, {parse:true});
		},

		accountConnected: function (account) {
			var self = this;
			account.getMessages('Inbox').then(function (messages) {
				self.radio.vent.trigger('mailbox:update', {mailbox:'INBOX', account: account, messages: messages});
			}, function (err) {
				// TODO
				console.log('Error getting inbox messages', err);
			});
		}

	});

	return AccountController;

});

define([
	'underscore',
	'controller'
], function (_, Controller) {

	var AccountController = Controller.extend({

		handers: {
			'account:add' : 'createAccount'
		},

		initialize: function (opts) {
			this.collection.on('change:connected', this.accountConnected.bind(this));
		},

		createAccount: function (options) {
			return this.collection.create(arguments, {parse:true});
		},

		accountConnected: function (account) {
			var self = this;
			account.getMessages('Inbox').then(function (messages) {
				self.radio.vent.trigger('mailbox:update', {mailbox:'INBOX', account: account, messages: messages});
			}).then(null, function (err) {
				// TODO
				console.log('Error getting inbox messages', err);
			});
		}

	});

	return AccountController;

});

Fix possible uncaught exception in retreiving messages


import React, { Component } from 'react'
import ClientCard from '../views/ClientCard'
import { Container } from 'semantic-ui-react'
import styled from 'styled-components'

const StyledLeads = styled.div`
  display: flex;
  flex-wrap: wrap;
`

class ClientsContainer extends Component {
  render() {
    console.log(this.props)
    const clients = this.props.clients.map(c => <ClientCard key={c.id} {...c} />)
    const monthly = this.props.clients.reduce((a, b) => {return a + b.monthly_rate}, 0)
    return (
      <Container>
        {monthly}
        <StyledLeads>
          {clients}
        </StyledLeads>
      </Container>
    )
  }
}

export default ClientsContainer

import React, { Component } from 'react'
import ClientCard from '../views/ClientCard'
import { Container } from 'semantic-ui-react'
import styled from 'styled-components'

const StyledLeads = styled.div`
  display: flex;
  flex-wrap: wrap;
`

class ClientsContainer extends Component {
  render() {
    const clients = this.props.clients.map(c =>
      <ClientCard key={c.id} {...c} />
    )
    const monthly = this.props.clients.reduce((a, b) => {
      return a + b.monthly_rate
    }, 0)
    return (
      <Container>
        {monthly}
        <StyledLeads>
          {clients}
        </StyledLeads>
      </Container>
    )
  }
}

export default ClientsContainer

Add total monthly amount to clients container


"use strict";

module.exports = {
    files: configuration.srcFiles.concat(configuration.testFiles),
    // Take care of linting and maintainability
    tasks: [
        "eslint",
        "exec:plato"
    ]
};

"use strict";

module.exports = {
    files: configuration.srcFiles.concat(configuration.testFiles),
    // Take care of linting and maintainability (don't use concurrent to allow configuration altering)
    tasks: [
        "jshint",
        "eslint",
        "exec:plato"
    ],
    options: {
        spawn: false
    }
};

Set spawn to false to manipulate configuration


var config = require('../config');
var raven = require('raven');

var client = config.log.url ? new raven.Client( config.log.url ) : false;

// Simple message
exports.message = function( message, level ){

    level = level || 'info';

        client.captureMessage( message, {level: level} );
        console.info(message);

}

// Error message
exports.error = function( message ){

    if (client)
        client.captureError(new Error( message ));
    else
        console.error(message);

}

var config = require('../config');
var raven = require('raven');

var client = config.log.url ? new raven.Client( config.log.url ) : false;

// Simple message
exports.message = function( message, level ){

    level = level || 'info';

    if (client) {
        client.captureMessage( message, {level: level} );
    }
    else {
        console.info(message);
    }
}

// Error message
exports.error = function( message ){

    if (client) {
        client.captureError(new Error( message ));
    }
    else {
        console.error(message);
    }

}

Fix syntax error introduced in 13fa7ba.


isic.views.TermsAcceptanceView = isic.View.extend({
    events: {
        'click #isic-terms-accept': function (event) {
            // Disable buttons while request is pending
            var buttons = this.$('.isic-terms-agreement-button-container button');
            buttons.prop('disabled', true);

            if (girder.currentUser) {
                girder.currentUser.setAcceptTerms(function () {
                    // Refresh page
                    Backbone.history.loadUrl();
                });
            } else {
                window.sessionStorage.setItem('acceptTerms', 'true');
                Backbone.history.loadUrl();
            }
        },
        'click #isic-terms-reject': function (event) {
            girder.events.trigger('g:navigateTo', isic.views.FrontPageView);
        }
    },

    initialize: function () {
        this.termsOfUseWidget = new isic.views.TermsOfUseWidget({
            parentView: this
        });

        this.render();
    },

    render: function () {
        this.$el.html(isic.templates.termsAcceptancePage());

        this.termsOfUseWidget.setElement(
            this.$('#isic-terms-of-use-container')).render();

        return this;
    }
}, {
    // Static methods
    hasAcceptedTerms: function () {
        if (girder.currentUser) {
            return girder.currentUser.canAcceptTerms();
        } else {
            return window.sessionStorage.getItem('acceptTerms') === 'true';
        }
    }
});

isic.router.route('termsAcceptance', 'termsAcceptance', function () {
    girder.events.trigger('g:navigateTo', isic.views.TermsAcceptanceView);
});

isic.views.TermsAcceptanceView = isic.View.extend({
    events: {
        'click #isic-terms-accept': function (event) {
            // Disable buttons while request is pending
            var buttons = this.$('.isic-terms-agreement-button-container button');
            buttons.prop('disabled', true);

            if (girder.currentUser) {
                girder.currentUser.setAcceptTerms(function () {
                    // Refresh page
                    Backbone.history.loadUrl();
                });
            } else {
                window.sessionStorage.setItem('acceptTerms', 'true');
                Backbone.history.loadUrl();
            }
        },
        'click #isic-terms-reject': function (event) {
            // Route to home page
            isic.router.navigate('', {trigger: true});
        }
    },

    initialize: function () {
        this.termsOfUseWidget = new isic.views.TermsOfUseWidget({
            parentView: this
        });

        this.render();
    },

    render: function () {
        this.$el.html(isic.templates.termsAcceptancePage());

        this.termsOfUseWidget.setElement(
            this.$('#isic-terms-of-use-container')).render();

        return this;
    }
}, {
    // Static methods
    hasAcceptedTerms: function () {
        if (girder.currentUser) {
            return girder.currentUser.canAcceptTerms();
        } else {
            return window.sessionStorage.getItem('acceptTerms') === 'true';
        }
    }
});

isic.router.route('termsAcceptance', 'termsAcceptance', function () {
    girder.events.trigger('g:navigateTo', isic.views.TermsAcceptanceView);
});

Use router to navigate to home page


'use strict';

'use strict';

const Base = require('./base');

/**
 * ApplicationCharge resource.
 *
 * @public
 */
class ApplicationCharge extends Base {
  /**
   * Creates an ApplicationCharge instance.
   *
   * @param {Shopify} shopify Reference to the Shopify instance
   */
  constructor(shopify) {
    super(shopify);

    this.name = 'application_charges';
    this.key = 'application_charge';
  }

  /**
   * Activates a previously accepted one-time application charge.
   *
   * @param {Number|String} id Application charge ID
   * @param {Object} params Application change properties
   * @return {Promise} Promise that resolves with the result
   * @public
   */
  activate(id, params) {
    const url = this.buildUrl(`${id}/activate`);
    return this.shopify.request(url, 'POST', undefined, {
      [this.key]: params
    });
  }
}

module.exports = ApplicationCharge;

Remove duplicate "use strict" statement


'use strict'

const express = require('express')
require('dotenv').config({path: '../.env'})

const app = express()
const port = process.env.SITE_PORT

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

app.get('/', (req, res) => {
    res.sendFile('index.html')
})

app.listen(port, () => {
    console.log('listening on port', port)
})

'use strict'

const express = require('express')
const dotenv = require('dotenv')

const result = dotenv.config()
if (result.error)
    dotenv.config({
        path: '../.env'
    })

const app = express()
const port = process.env.SITE_PORT

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

app.get('/', (req, res) => {
    res.sendFile('index.html')
})

app.listen(port, () => {
    console.log('listening on port', port)
})

Fix not finding .env on live


import settings from 'electron-settings';
import {
  SET_APP_SETTINGS,
  SET_AUDIO_OFF,
  SET_AUDIO_ON,
  SET_ELECTRON_SETTINGS
} from './types';

const initialState = {
  audioDisabled: true
};

export default (state = initialState, action) => {
  switch (action.type) {

    case SET_APP_SETTINGS: {
      const { data } = action;
      return { ...data };
    }

    case SET_AUDIO_OFF: {
      return { ...state, audioDisabled: true };
    }

    case SET_AUDIO_ON: {
      return { ...state, audioDisabled: false };
    }

    case SET_ELECTRON_SETTINGS: {
      const { keyPath, value, options } = action;
      settings.set(keyPath, value, options);
      return { ...state };
    }

    default: {
      return state;
    }
  }
};

import settings from 'electron-settings';
import {
  SET_APP_SETTINGS,
  SET_AUDIO_OFF,
  SET_AUDIO_ON,
  SET_ELECTRON_SETTINGS
} from './types';

const initialState = {
  audioDisabled: false
};

export default (state = initialState, action) => {
  switch (action.type) {

    case SET_APP_SETTINGS: {
      const { data } = action;
      return { ...data };
    }

    case SET_AUDIO_OFF: {
      return { ...state, audioDisabled: true };
    }

    case SET_AUDIO_ON: {
      return { ...state, audioDisabled: false };
    }

    case SET_ELECTRON_SETTINGS: {
      const { keyPath, value, options } = action;
      settings.set(keyPath, value, options);
      return { ...state };
    }

    default: {
      return state;
    }
  }
};

Change default audio state to play sound


// @flow
import React from 'react'

module.exports = (options: any) =>
  React.createClass({
    displayName: 'GoogleFont',

    render () {
      // Create family + styles string
      let fontsStr = ''
      const fonts = options.googleFonts.map((font) => {
        let str = ''
        str += font.name.split(' ').join('+')
        str += ':'
        str += font.styles.join(',')

        return str
      })

      fontsStr = fonts.join('|')

      if (fontsStr) {
        return React.DOM.link({
          href: `//fonts.googleapis.com/css?family=${fontsStr}`,
          rel: 'stylesheet',
          type: 'text/css',
        })
      } else {
        return null
      }
    },
  })

// @flow
import React from 'react'

module.exports = (options: any) =>
  React.createClass({
    displayName: 'GoogleFont',

    render () {
      // Create family + styles string
      let fontsStr = ''
      if (options.googleFonts) {
        const fonts = options.googleFonts.map((font) => {
          let str = ''
          str += font.name.split(' ').join('+')
          str += ':'
          str += font.styles.join(',')

          return str
        })

        fontsStr = fonts.join('|')

        if (fontsStr) {
          return React.DOM.link({
            href: `//fonts.googleapis.com/css?family=${fontsStr}`,
            rel: 'stylesheet',
            type: 'text/css',
          })
        } else {
          return null
        }
      } else {
        return null
      }
    },
  })

Check that options declares Google Fonts before building component


'use strict';

module.exports.run = function (test, Heap) {
  test('should insert items into the heap', function (t) {
    var heap = new Heap();
    heap.insert(1, null);
    heap.insert(2, null);
    heap.insert(3, null);
    heap.insert(4, null);
    heap.insert(5, null);
    t.same(heap.size(), 5);
    t.end();
  });

  test('should return the inserted node', function (t) {
    var heap = new Heap();
    var ret = heap.insert(1, {foo: 'bar'});
    t.is(ret.key, 1);
    t.same(ret.value, {foo: 'bar'});
    t.end();
  });
};

'use strict';

module.exports.run = function (test, Heap) {
  test('should insert items into the heap', function (t) {
    var heap = new Heap();
    heap.insert(1, null);
    heap.insert(2, null);
    heap.insert(3, null);
    heap.insert(4, null);
    heap.insert(5, null);
    t.same(heap.size(), 5);
    t.end();
  });

  test('should return the inserted node', function (t) {
    var heap = new Heap();
    var ret = heap.insert(1, {foo: 'bar'});
    t.is(ret.key, 1);
    t.same(ret.value, {foo: 'bar'});
    t.end();
  });

  test('should insert multiple items with the same key', function (t) {
    var heap = new Heap();
    heap.insert(1, null);
    heap.insert(1, null);
    t.is(1, heap.extractMinimum().key);
    t.is(1, heap.extractMinimum().key);
    t.end();
  });
};

Add test that checks duplicate keys work


var IPHistory = (function() {
    'use strict';

    function makeRequest() {
        var request = {login_history: 1, limit: 50};
        BinarySocket.send(request);
    }

    function responseHandler(msg) {
        var response = JSON.parse(msg.data);
        if (!response || response.msg_type !== 'login_history') {
            return;
        }
        if (response.error && response.error.message) {
            IPHistoryUI.displayError(response.error.message);
        }
        var parsed = response.login_history.map(IPHistoryData.parse);
        IPHistoryUI.displayTable(parsed);
    }

    // localize, title, create tables
    // register the callback on IPHistoryQueue
    function init() {
        IPHistoryUI.init();
        makeRequest();
    }

    function clean() {
        IPHistoryUI.clean();
    }

    return {
        init: init,
        clean: clean,
        responseHandler: responseHandler,
    };
})();

var IPHistory = (function() {
    'use strict';

    function makeRequest() {
        var request = {login_history: 1, limit: 50};
        BinarySocket.send(request);
    }

    function responseHandler(msg) {
        var response = JSON.parse(msg.data);
        if (!response || response.msg_type !== 'login_history') {
            return;
        }
        if (response.error && response.error.message) {
            return IPHistoryUI.displayError(response.error.message);
        }
        var parsed = response.login_history.map(IPHistoryData.parse);
        IPHistoryUI.displayTable(parsed);
    }

    // localize, title, create tables
    // register the callback on IPHistoryQueue
    function init() {
        IPHistoryUI.init();
        makeRequest();
    }

    function clean() {
        IPHistoryUI.clean();
    }

    return {
        init: init,
        clean: clean,
        responseHandler: responseHandler,
    };
})();

Return immediately on error as per old behaviour


var self = require('sdk/self');

// a dummy function, to show how tests work.
// to see how to test this function, look at test/test-index.js
function dummy(text, callback) {
  callback(text);
}

exports.dummy = dummy;

var buttons = require('sdk/ui/button/action');
var tabs = require("sdk/tabs");

var button = buttons.ActionButton({
  id: "idea-town-link",
  label: "Idea Town",
  icon: {
    "16": "./icon-16.png",
    "32": "./icon-32.png",
    "64": "./icon-64.png"
  },
  onClick: handleClick
});

function handleClick(state) {
  tabs.open("http://developer.mozilla.org/");
}

var self = require('sdk/self');

// a dummy function, to show how tests work.
// to see how to test this function, look at test/test-index.js
function dummy(text, callback) {
  callback(text);
}

exports.dummy = dummy;

var buttons = require('sdk/ui/button/action');
var tabs = require("sdk/tabs");

var button = buttons.ActionButton({
  id: "idea-town-link",
  label: "Idea Town",
  icon: {
    "16": "./icon-16.png",
    "32": "./icon-32.png",
    "64": "./icon-64.png"
  },
  onClick: handleClick
});

function handleClick(state) {
  tabs.open("https://ideatown.firefox.com/");
}

Update the idea town URL


import { Meteor } from 'meteor/meteor';

import exportFiles from '../collection.js';

Meteor.publish('exportFiles.all', function publishExportFilesAll() {
  let cursor;
  if (this.userId) {
    cursor = exportFiles.find();
  } else {
    cursor = this.ready();
  }
  return cursor;
});

import { Meteor } from 'meteor/meteor';

import exportFiles from '../collection.js';

Meteor.publish('exportFiles.all', function publishExportFilesAll() {
  let cursor;
  if (this.userId) {
    cursor = exportFiles.find({}, { sort: { uploadedAt: -1 }, limit: 1 });
  } else {
    cursor = this.ready();
  }
  return cursor;
});

Make sure most recent export file is published.


import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';
import { get } from '@ember/object';
import C from 'ui/utils/constants';
import { isDevBuild } from 'shared/utils/parse-version';

export default Route.extend({
  access:      service(),
  settings:    service(),
  globalStore: service(),

  model() {
    let promises = [];

    if ( get(this, 'access.firstLogin') ) {
      promises.push(get(this, 'globalStore').find('preference'));

      promises.push(get(this, 'settings').load([
        C.SETTING.VERSION_RANCHER,
        C.SETTING.TELEMETRY,
        C.SETTING.EULA_AGREED,
        C.SETTING.UI_DEFAULT_LANDING
      ]));
    }

    return Promise.all(promises).then(() => {
      const cur = get(this, `settings.${ C.SETTING.TELEMETRY }`);
      const version = get(this, `settings.${ C.SETTING.VERSION_RANCHER }`);
      let optIn;

      if ( !version || isDevBuild(version) ) {
        // For dev builds, default to opt out
        optIn = (cur === 'in');
      } else {
        // For releases, default to opt in
        optIn = (cur !== 'out');
      }

      return {
        user: get(this, 'access.me'),
        code: get(this, 'access.userCode') || '',
        optIn,
      };
    });
  },

  activate() {
    $('BODY').addClass('container-farm'); // eslint-disable-line
  },

  deactivate() {
    $('BODY').removeClass('container-farm'); // eslint-disable-line
  },
});

import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';
import { get } from '@ember/object';
import C from 'ui/utils/constants';
import { isDevBuild } from 'shared/utils/parse-version';

export default Route.extend({
  access:      service(),
  settings:    service(),
  globalStore: service(),

  model() {
    let promises = [];

    if ( get(this, 'access.firstLogin') ) {
      promises.push(get(this, 'globalStore').find('preference'));
      promises.push(get(this, 'settings').loadAll());
    }

    return Promise.all(promises).then(() => {
      const cur = get(this, `settings.${ C.SETTING.TELEMETRY }`);
      const version = get(this, `settings.${ C.SETTING.VERSION_RANCHER }`);
      let optIn;

      if ( !version || isDevBuild(version) ) {
        // For dev builds, default to opt out
        optIn = (cur === 'in');
      } else {
        // For releases, default to opt in
        optIn = (cur !== 'out');
      }

      return {
        user: get(this, 'access.me'),
        code: get(this, 'access.userCode') || '',
        optIn,
      };
    });
  },

  activate() {
    $('BODY').addClass('container-farm'); // eslint-disable-line
  },

  deactivate() {
    $('BODY').removeClass('container-farm'); // eslint-disable-line
  },
});

Load all settings instead of explicit list for first login


angular.module('pmsiplan').directive('resourceHistory', ['AngularDataStore', function(AngularDataStore) {
    return {
        templateUrl: 'partials/directive/resource-history.html',
        scope: {
            resourceId: '=id',
            historyEntries: '=history'
        },
        link: function(scope, element, attrs) {
            var callback = function(history) {
                scope.history = history
                    .slice(-50)
                    .map(function(entry) {
                        entry.content = JSON.parse(entry.content);

                        return entry;
                    })
                    .filter(function(entry) {
                        return !scope.resourceId || entry.content._id === scope.resourceId;
                    })
                    .map(function(entry) {
                        if(entry.content.project) {
                            AngularDataStore.findBy('project', {_id: entry.content.project}).then(function(projects) {
                                scope.project = projects[0];
                            });
                        }

                        if(entry.content.delivery) {
                            AngularDataStore.findBy('delivery', {_id: entry.content.delivery}).then(function(deliveries) {
                                scope.delivery = deliveries[0];
                            });
                        }

                        return entry;
                    });
            };

            if(attrs.type) {
                scope.type = attrs.type;

                AngularDataStore.findBy('histo', { resource: attrs.type }).then(callback);
            }

            if(scope.historyEntries) {
                callback(scope.historyEntries);
            }
        }
    };
}]);

angular.module('pmsiplan').directive('resourceHistory', ['AngularDataStore', function(AngularDataStore) {
    return {
        templateUrl: 'partials/directive/resource-history.html',
        scope: {
            resourceId: '=id',
            historyEntries: '=history'
        },
        link: function(scope, element, attrs) {
            var callback = function(history) {
                scope.history = history
                    .slice(-50)
                    .map(function(entry) {
                        entry.content = JSON.parse(entry.content);

                        return entry;
                    })
                    .filter(function(entry) {
                        return !scope.resourceId || entry.content._id === scope.resourceId;
                    })
                    .map(function(entry) {
                        if(entry.content.project) {
                            AngularDataStore.findBy('project', {_id: entry.content.project}).then(function(projects) {
                                entry.project = projects[0];
                            });
                        }

                        if(entry.content.delivery) {
                            AngularDataStore.findBy('delivery', {_id: entry.content.delivery}).then(function(deliveries) {
                                entry.delivery = deliveries[0];
                            });
                        }

                        return entry;
                    });
            };

            if(attrs.type) {
                scope.type = attrs.type;

                AngularDataStore.findBy('histo', { resource: attrs.type }).then(callback);
            }

            if(scope.historyEntries) {
                callback(scope.historyEntries);
            }
        }
    };
}]);

Fix a bug in history


define(["jquery", "underscore", "backbone"], function($, _, Backbone) {
	var Utils = {};

	Utils.logIn = function() {
		$.ajax({
			url: '/service/me/login',
			async: false,
			dataType: 'json'
		});
	};

	Utils.loadView = function(viewToLoad) {
		$('#page-content').html("");
		if (typeof viewToLoad === 'function') {
			new viewToLoad({
				el: '#page-content'
			});
		} else {
			viewToLoad.setElement('#page-content');
			viewToLoad.render();
		}
	};

	return Utils;
});

define(["jquery", "underscore", "backbone"], function($, _, Backbone) {
	var Utils = {};

	Utils.logIn = function(response) {
		$.ajax({
			url: '/service/me/login?token=',
			async: false,
			dataType: 'json'
		});
	};

	Utils.loadView = function(viewToLoad) {
		$('#page-content').html("");
		if (typeof viewToLoad === 'function') {
			new viewToLoad({
				el: '#page-content'
			});
		} else {
			viewToLoad.setElement('#page-content');
			viewToLoad.render();
		}
	};

	return Utils;
});

Prepare to pass OAuth token.


// @license
// Copyright (c) 2014 The Polymer Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//    * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//    * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//    * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Fix syntax error in `ep06`