import mobx from 'mobx';
import spy from './spy';

export default function dev(store, config) {
  if (typeof window === 'undefined' || !window.devToolsExtension) return store;

  if (mobx.isObservable(store)) {
    spy(store, config);
  } else if (typeof store === 'function') {
    store = class extends store {
      constructor() {
        super();
        spy(this, config);
      }
    };
  } else {
    console.warn(`Passed ${typeof store} to mobx-remotedev, which is not an observable.`);
  }

  return store;
}

import mobx from 'mobx';
import spy from './spy';

export default function dev(store, config) {
  if (typeof window === 'undefined' || !window.devToolsExtension) return store;

  if (mobx.isObservable(store)) {
    spy(store, config);
  } else if (typeof store === 'function') {
    store = class extends store {
      constructor(...args) {
        super(...args);
        spy(this, config);
      }
    };
  } else {
    console.warn(`Passed ${typeof store} to mobx-remotedev, which is not an observable.`);
  }

  return store;
}

Support arguments for the inherited class constructor


PRESTATION_TO_TEST_POSITION = 1
PRESTATION_NAME = /Prime d’activité/
PRESTATION_DESCRIPTION = /revenus modestes/
HAS_PRESTATION_WARNING = false
HAS_PRESTATION_ENGAGER_DEMARCHES_LINK = true

PRESTATION_TO_TEST_POSITION = 1
PRESTATION_NAME = /Prime d’activité/
PRESTATION_DESCRIPTION = /complète les revenus/
HAS_PRESTATION_WARNING = false
HAS_PRESTATION_ENGAGER_DEMARCHES_LINK = true

Fix expected text in integration test


var Web3 = require("web3");

var wrapper = require('./wrapper');

module.exports = {
  wrap: function(provider, options) {
    return wrapper.wrap(provider, options);
  },

  create: function(options) {
    var provider;

    if (options.provider && typeof options.provider == "function") {
      provider = options.provider();
    } else if (options.provider) {
      provider = options.provider;
    } else {
      provider = new Web3.providers.HttpProvider("http://" + options.host + ":" + options.port);
    }

    return this.wrap(provider, options);
  },

  test_connection: function(provider, callback) {
    var web3 = new Web3();
    var fail = new Error("Could not connect to your RPC client. Please check your RPC configuration.");

    web3.setProvider(provider);

    web3
      .eth
      .getCoinbase()
      .then(coinbase => callback(null, coinbase))
      .catch(e => callback(fail, null));
  }
};

var Web3 = require("web3");

var wrapper = require('./wrapper');

module.exports = {
  wrap: function(provider, options) {
    return wrapper.wrap(provider, options);
  },

  create: function(options) {
    var provider;

    if (options.provider && typeof options.provider == "function") {
      provider = options.provider();
    } else if (options.provider) {
      provider = options.provider;
    } else if (options.websockets) {
      provider = new Web3.providers.WebsocketProvider("ws://" + options.host + ":" + options.port);
    } else {
      provider = new Web3.providers.HttpProvider("http://" + options.host + ":" + options.port);
    }

    return this.wrap(provider, options);
  },

  test_connection: function(provider, callback) {
    var web3 = new Web3();
    var fail = new Error("Could not connect to your RPC client. Please check your RPC configuration.");

    web3.setProvider(provider);

    web3
      .eth
      .getCoinbase()
      .then(coinbase => callback(null, coinbase))
      .catch(e => callback(fail, null));
  }
};

Enable a websockets config option


var signinSSODialogHelperInst = window.optly.mrkt.form.signin({formId: 'signin-sso-form'});

new Oform({
  selector: '#signin-sso-form',
  middleware: w.optly.mrkt.Oform.defaultMiddleware
}).on('before', function() {
  signinSSODialogHelperInst.processingAdd();
  return true;
}).on('error', function(){
  signinSSODialogHelperInst.processingRemove({callee: 'error'});
  signinSSODialogHelperInst.showOptionsError({error: 'UNEXPECTED'});
  window.analytics.track('signin sso xhr error', {
    category: 'account',
    label: w.location.pathname
  }, {
    integrations: {
      Marketo: false
    }
  });
}).on('load', function(result){
  var responseObj = result.XHR ? JSON.parse(result.XHR.response) : {};
  var status = result.XHR ? result.XHR.status : null;

  if (status === 200 && responseObj.url) {
    window.location = responseObj.url;
  } else if (responseObj.succeeded === false && responseObj.error) {
    $('#js-sso-error').text(responseObj.error);
  }
}).on('done', function(){
  signinSSODialogHelperInst.processingRemove({callee: 'done'});
  if (document.body.classList.contains('oform-error')) {
    signinSSODialogHelperInst.showOptionsError();
  }
}).on('validationerror', w.optly.mrkt.Oform.validationError);

var signinSSODialogHelperInst = window.optly.mrkt.form.signin({formId: 'signin-sso-form'});

new Oform({
  selector: '#signin-sso-form',
  middleware: w.optly.mrkt.Oform.defaultMiddleware
}).on('before', function() {
  signinSSODialogHelperInst.processingAdd();
  return true;
}).on('error', function(){
  signinSSODialogHelperInst.processingRemove({callee: 'error'});
  signinSSODialogHelperInst.showOptionsError({error: 'UNEXPECTED'});
  window.analytics.track('signin sso xhr error', {
    category: 'account',
    label: w.location.pathname
  }, {
    integrations: {
      Marketo: false
    }
  });
}).on('load', function(result){
  var responseObj = result.XHR ? JSON.parse(result.XHR.response) : {};
  var status = result.XHR ? result.XHR.status : null;

  if (status === 200 && responseObj.url) {
    window.location = responseObj.url;
  } else if (responseObj.succeeded === false && responseObj.error) {
    signinSSODialogHelperInst.processingRemove({callee: 'error'});
    $('#js-sso-error').text(responseObj.error);
  }
}).on('done', function(){
  signinSSODialogHelperInst.processingRemove({callee: 'done'});
  if (document.body.classList.contains('oform-error')) {
    signinSSODialogHelperInst.showOptionsError();
  }
}).on('validationerror', w.optly.mrkt.Oform.validationError);

Remove the processing feature when there is an error.


import apis from '../apis'

export function getSuggestions(name) {
  return dispatch => {
    const url = apis.GET_SUGGESTIONS(encodeURIComponent(name))
    fetch(url)
      .then(res => res.json())
      .then(games => {
        dispatch({ type: 'GET_SUGGESTIONS_SUCCESS', suggestions: games })
      })
      .catch(error => {
        dispatch({ type: 'FETCH_ERROR', error, url })
      })
  }
}

import apis from '../apis'

export function getSuggestions(name) {
  return (dispatch, getState) => {
    const state = getState()

    if (!state.app.get('loading')) {
      const url = apis.GET_SUGGESTIONS(encodeURIComponent(name))
      fetch(url)
        .then(res => res.json())
        .then(games => {
          dispatch({ type: 'GET_SUGGESTIONS_SUCCESS', suggestions: games })
        })
        .catch(error => {
          dispatch({ type: 'FETCH_ERROR', error, url })
        })
    }
  }
}

Fix bug when the recommendations list show while loading


"use strict";

var app = angular.module("VinculacionApp", ['ui.router', 'ngAnimate']);

app.config(['$stateProvider', '$urlRouterProvider',function($stateProvider, $urlRouterProvider) {
	$urlRouterProvider.otherwise('/');

	$stateProvider

		.state('landing', {
			url: '/',
			templateUrl: '../templates/landing.html'
		})

		.state('registro', {
			url: '/registro',
			templateUrl: '../templates/registro.html'
		})

		.state('home', {
			url: '/home',
			templateUrl: '../templates/dashboard.html'
		})

		.state('home.proyectos', {
			url: '/proyectos',
			templateUrl: '../templates/proyectos.html'
		})

		.state('home.proyecto', {
			url: '/proyecto',
			templateUrl: '../templates/proyecto.html'
		})

		.state('home.horas', {
			url: '/horas',
			templateUrl: '../templates/horas.html'
		})

		.state('home.solicitudes', {
			url: '/solicitudes',
			templateUrl: '../templates/solicitudes.html'
		})

		.state('home.solicitud', {
			url: '/solicitud',
			templateUrl: '../templates/solicitud.html'
		});

}]);

"use strict";

var app = angular.module("VinculacionApp", ['ui.router', 'ngAnimate']);

app.config(['$stateProvider', '$urlRouterProvider',function($stateProvider, $urlRouterProvider) {
	$urlRouterProvider.otherwise('/');

	$stateProvider

		.state('landing', {
			url: '/',
			templateUrl: '../templates/landing.html'
		})

		.state('registro', {
			url: '/registro',
			templateUrl: '../templates/registro.html',
			controller: 'RegistroCtrl as registro'
		})

		.state('home', {
			url: '/home',
			templateUrl: '../templates/dashboard.html'
		})

		.state('home.proyectos', {
			url: '/proyectos',
			templateUrl: '../templates/proyectos.html'
		})

		.state('home.proyecto', {
			url: '/proyecto',
			templateUrl: '../templates/proyecto.html'
		})

		.state('home.horas', {
			url: '/horas',
			templateUrl: '../templates/horas.html'
		})

		.state('home.solicitudes', {
			url: '/solicitudes',
			templateUrl: '../templates/solicitudes.html'
		})

		.state('home.solicitud', {
			url: '/solicitud',
			templateUrl: '../templates/solicitud.html'
		});

}]);

Set controller for register view


$(document).ready(function() {
	console.log("works")

	setTimeout(refreshTickets, 10000);

});

function refreshTickets() {
	// event.preventDefault();
	window.location.href = window.location.href;
	$.ajax({
		type: 'get',
		url: '/tickets',
		data: $(this).serialize()
	}).success(function(response){
		console.log("works")
		console.log(response)
	}).fail({
		console.log("works")
		console.log(response)
	})
}

$(document).ready(function() {
	console.log("works")

	$('#tickets').ready(function(){
		setTimeout(refreshTickets, 10000);
	})

	$('#')

});

function refreshTickets() {
	// event.preventDefault();
	window.location.href = window.location.href;  //BUGBUG
	$.ajax({
		type: 'get',
		url: '/tickets',
		data: $(this).serialize()
	}).success(function(response){
		console.log("works")
		console.log(response)
	}).fail({
		console.log("works")
		console.log(response)
	})
}

Modify refresh page js slightly


import del from 'del';
import gulp from 'gulp';
import mergeStream from 'merge-stream';
import loadPlugins from 'gulp-load-plugins';
import cssnextPlugin from 'postcss-cssnext';
import {cssSrcFolder, cssBuildFolder} from './common';

const plugins = loadPlugins();

gulp.task('css-build-src', () => {
  return gulp.src([`${cssSrcFolder}/**/*.scss`, `!${cssSrcFolder}/*.scss`])
    .pipe(plugins.sass({outputStyle: 'compressed'}))
    .pipe(plugins.postcss([cssnextPlugin()]))
    .pipe(gulp.dest(cssBuildFolder));
});

gulp.task('css-build-assets', () => {
  return gulp.src(`${cssSrcFolder}/*/**/!(package.json|*.md|*.scss)`)
    .pipe(gulp.dest(cssBuildFolder));
});

gulp.task('css-build-variables-and-mixins-package', () => {
  return mergeStream(
    gulp.src([`${cssSrcFolder}/pui-variables.scss`, `${cssSrcFolder}/mixins.scss`]),
  ).pipe(gulp.dest(`${cssBuildFolder}/variables-and-mixins`));
});

gulp.task('css-clean', callback => del([cssBuildFolder], callback));

gulp.task('css-build', gulp.series('css-clean',
  'css-build-src',
  'css-build-assets',
  'css-build-variables-and-mixins-package'
));

import del from 'del';
import gulp from 'gulp';
import mergeStream from 'merge-stream';
import loadPlugins from 'gulp-load-plugins';
import cssnextPlugin from 'postcss-cssnext';
import {cssSrcFolder, cssBuildFolder, copyrightHeader} from './common';

const plugins = loadPlugins();

gulp.task('css-build-src', () => {
  return gulp.src([`${cssSrcFolder}/**/*.scss`, `!${cssSrcFolder}/*.scss`])
    .pipe(plugins.sass({outputStyle: 'compressed'}))
    .pipe(plugins.postcss([cssnextPlugin()]))
    .pipe(plugins.header(copyrightHeader))
    .pipe(gulp.dest(cssBuildFolder));
});

gulp.task('css-build-assets', () => {
  return gulp.src(`${cssSrcFolder}/*/**/!(package.json|*.md|*.scss)`)
    .pipe(gulp.dest(cssBuildFolder));
});

gulp.task('css-build-variables-and-mixins-package', () => {
  return mergeStream(
    gulp.src([`${cssSrcFolder}/pui-variables.scss`, `${cssSrcFolder}/mixins.scss`]),
  ).pipe(gulp.dest(`${cssBuildFolder}/variables-and-mixins`));
});

gulp.task('css-clean', callback => del([cssBuildFolder], callback));

gulp.task('css-build', gulp.series('css-clean',
  'css-build-src',
  'css-build-assets',
  'css-build-variables-and-mixins-package'
));

Add copyright header to distributed CSS


var NULL_ADDRESS = '0x0000000000000000000000000000000000000000';

function getTransactionError(func) {
  return Promise.resolve().then(func)
    .then(function(txid) {
      var tx = web3.eth.getTransaction(txid);
      var txr = web3.eth.getTransactionReceipt(txid);
      if (txr.gasUsed === tx.gas) throw new Error("all gas used");
    })
    .catch(function(err) {
      return err;
    });
}

contract("SpiceHours", function(accounts) {

  describe("test", function() {

    it("should not throw an error for owner", function() {
      var contract = SpiceHours.deployed();
      return getTransactionError(function() {
        return contract.test();
      }).then(function(err) {
        assert.isUndefined(err, "owner should have access");
      });
    });

    it("should throw an error for others", function() {
      var contract = SpiceHours.deployed();
      return getTransactionError(function() {
        return contract.test({from: accounts[1]});
      }).then(function(err) {
        assert.isDefined(err, "others should not have access");
      });
    });
  });
});

var NULL_ADDRESS = '0x0000000000000000000000000000000000000000';

function getTransactionError(func) {
  return Promise.resolve().then(func)
    .then(function(txid) {
      var tx = web3.eth.getTransaction(txid);
      var txr = web3.eth.getTransactionReceipt(txid);
      if (txr.gasUsed === tx.gas) throw new Error("all gas used");
    })
    .catch(function(err) {
      return err;
    });
}

contract("SpiceHours", function(accounts) {

  describe("balance", function() {

    it("should be zero in the beginning", function() {
      var contract = SpiceHours.deployed();
      return contract.balance.call(accounts[0]).then(function(balance) {
        assert.equal(balance.valueOf(), 0, "balance should be zero");
      });
    });
  });
});

Fix tests after contract change broke them.


module.exports = function(grunt, config, parameters, done) {

	function endForError(e) {
		process.stderr.write(e.message || e);
		done(false);
	}

	try {
		var rimraf = require('rimraf'),
			fs = require('fs'),
			download = require('download'),
			path = "./release";

		rimraf.sync(path);
		fs.mkdir(path);

		// Download archive from git
		process.stdout.write("Downloading Archive...\n");
		var stream = download('https://github.com/concrete5/concrete5/archive/master.zip', path, {
			extract: true
		});
		stream.on('close', function() {
			done();
		});

	}
	catch(e) {
		endForError(e);
		return;
	}
};

module.exports = function(grunt, config, parameters, done) {

	function endForError(e) {
		process.stderr.write(e.message || e);
		done(false);
	}

	try {
		var shell = require('shelljs'),
			fs = require('fs'),
			download = require('download'),
			path = "./release";

		shell.rm('-rf', path);
		fs.mkdir(path);

		// Download archive from git
		process.stdout.write("Downloading Archive...\n");
		var stream = download('https://github.com/concrete5/concrete5/archive/master.zip', path, {
			extract: true
		});
		stream.on('close', function() {
			done();
		});

	}
	catch(e) {
		endForError(e);
		return;
	}
};

Use shelljs instead of rimraf


App = {
  placeAnchorHooks : function() {
    $('[data-href]').on('click',function() {
      App.Router.navigate( $(this).attr('data-href'), true );
      _.delay(function() { window.scrollTo(0,0); }, 250);
    });
  }
};

$(document).ready(function() {
  App.Router = new Router;
  Backbone.history.start({ pushState: true });

  App.placeAnchorHooks();

  setTimeout(function() { window.scrollTo(0, 0); }, 1000);
  $(window).bind('orientationchange', function() { scrollTo(0, 0); });
});

App = {
  placeAnchorHooks : function() {
    $('[data-href]').on('click',function() {
      App.Router.navigate( $(this).attr('data-href'), true );
      _.delay(function() { window.scrollTo(0,0); }, 250);
    });
  }
};

$(document).ready(function() {
  App.Router = new Router;
  Backbone.history.start({ pushState: location.href.indexOf("file://") !== 0 });

  App.placeAnchorHooks();

  setTimeout(function() { window.scrollTo(0, 0); }, 1000);
  $(window).bind('orientationchange', function() { scrollTo(0, 0); });
});

Disable pushState for file: protocl URLs


/*
Language: Extended Backus-Naur Form
Author: Alex McKibben <alex@nullscope.net>
*/

function(hljs) {
    var specialSequenceMode = {
        className: "meta",
        begin: /\?.*\?/
    };

    return {
        contains: [
            specialSequenceMode,
            hljs.COMMENT(/\(\*/, /\*\)/),
            // terminals
            hljs.APOS_STRING_MODE, hljs.QUOTE_STRING_MODE
        ]
    };
}

/*
Language: Extended Backus-Naur Form
Author: Alex McKibben <alex@nullscope.net>
*/

function(hljs) {
    var nonTerminalMode = {
        className: "attribute",
        begin: /[a-zA-Z][a-zA-Z-]*([\s-]+[a-zA-Z][a-zA-Z]*)*/
    };

    var specialSequenceMode = {
        className: "meta",
        begin: /\?.*\?/
    };

    return {
        contains: [
            nonTerminalMode,
            specialSequenceMode,
            hljs.COMMENT(/\(\*/, /\*\)/),
            // terminals
            hljs.APOS_STRING_MODE, hljs.QUOTE_STRING_MODE
        ]
    };
}

Implement attribute (non-terminal, rule name) highlighting.


import DS from 'ember-data';

export default DS.Transform.extend({
  deserialize: function(serialized) {
    var map = {
      0: 'New',
      20: 'Started',
      25: 'Reviewed',
      30: 'Finished',
    };
    return map[serialized];
  },

  serialize: function(deserialized) {
    var map = {
      'New': 0,
      'Started': 20,
      'Reviewed': 25,
      'Finished': 30,
};
    return map[deserialized];
  }
});

import DS from 'ember-data';

export default DS.Transform.extend({
  deserialize: function(serialized) {
    var map = {
      0: 'New',
      10: 'Built',
      20: 'Started',
      25: 'Reviewed',
      30: 'Finished',
    };
    return map[serialized];
  },

  serialize: function(deserialized) {
    var map = {
      'New': 0,
      'Built': 10,
      'Started': 20,
      'Reviewed': 25,
      'Finished': 30,
};
    return map[deserialized];
  }
});

Add `Built` to round status


class Container{
    constructor(){
        this.services = {};
    }

    destroy(){
        delete this.services;
        this.services = {};
    }

    /**
     * Defines a service on the container. The service is accessed
     * directly as a property, but is not actually instantiated
     * before it is called.
     *
     * The service is only instantiated once.
     */
    service(name, cb){
        Object.defineProperty(this, name, {
            get: () => {
                if(!this.services.hasOwnProperty(name)){
                    this.services[name] = cb(this);
                }

                return this.services[name];
            }
        });

        return this;
    }

    /**
     * Define a factory function on the container.
     * The factory is accessed directly as a property,
     * and is instantiated every time the property is used.
     */
    factory(name, cb){
        Object.defineProperty(this, name, {
            get: () => {
                return cb(this);
            }
        });

        return this;
    }

    /**
     * A service provider is a class that uses
     * a register function to register all its related dependencies.
     * The container is passed to this function when the provider
     * registers itself here.
     */
    register(provider){
        provider.register(this);
    }

    /**
     * Helper function for binding constructor arguments.
     *
     * We also need it in order to set static properties to the bound constructor,
     * since React expects to get those directly from the element type.
     *
     * And lastly, we don't need to pass props and context to the Component,
     * since those are also set after React has constructed the component.
     * Admittedly, this should be done, but is not strictly necessary.
     */
    bindElement(elem, ...args){
        let f = elem.bind(null, ...args);

        /*
         Need to change the display name so we get something
         better than "bound something something"
        */
        f.displayName = elem.name;

        /*
        Also need to set various other static properties
         */
        f.defaultProps = elem.defaultProps;
        f.propTypes = elem.propTypes;
        f.contextTypes = elem.contextTypes;
        f.childContextTypes = elem.childContextTypes;

        return f;
    }
}

module.exports = Container;

class Container{
    constructor(){
        this.services = {};
    }

    /**
     * Defines a service on the container. The service is accessed
     * directly as a property, but is not actually instantiated
     * before it is called.
     *
     * The service is only instantiated once.
     */
    service(name, cb){
        Object.defineProperty(this, name, {
            get: () => {
                if(!this.services.hasOwnProperty(name)){
                    this.services[name] = cb(this);
                }

                return this.services[name];
            },
            configurable: true,
            enumerable: true
        });

        return this;
    }
}

module.exports = Container;

Remove old stuff that's not really needed


/*global defineSuite*/
defineSuite(['DynamicScene/KmlDataSource',
             'DynamicScene/DynamicObjectCollection',
             'Core/loadXML',
             'Core/Event'
            ], function(
                    KmlDataSource,
                    loadXML,
                    DynamicObjectCollection,
                    Event) {
    "use strict";
    /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/

    it('default constructor has expected values', function() {
        var dataSource = new KmlDataSource();
        expect(dataSource.getChangedEvent()).toBeInstanceOf(Event);
        expect(dataSource.getErrorEvent()).toBeInstanceOf(Event);
        expect(dataSource.getClock()).toBeUndefined();
        expect(dataSource.getDynamicObjectCollection()).toBeInstanceOf(DynamicObjectCollection);
        expect(dataSource.getDynamicObjectCollection().getObjects().length).toEqual(0);
        expect(dataSource.getIsTimeVarying()).toEqual(false);
    });

    it('Test loading Kml', function() {
        var dataSource = new KmlDataSource();
        var url = 'http://localhost:8080/Apps/CesiumViewer/Gallery/KML_Samples.kml';

        dataSource.loadUrl(url);
    });
});

/*global defineSuite*/
defineSuite(['DynamicScene/KmlDataSource',
             'DynamicScene/DynamicObjectCollection',
             'Core/loadXML',
             'Core/Event'
            ], function(
                    KmlDataSource,
                    loadXML,
                    DynamicObjectCollection,
                    Event) {
    "use strict";
    /*global jasmine,describe,xdescribe,it,xit,expect,beforeEach,afterEach,beforeAll,afterAll,spyOn,runs,waits,waitsFor*/

    it('default constructor has expected values', function() {
        var dataSource = new KmlDataSource();
        expect(dataSource.getChangedEvent()).toBeInstanceOf(Event);
        expect(dataSource.getErrorEvent()).toBeInstanceOf(Event);
        expect(dataSource.getClock()).toBeUndefined();
        expect(dataSource.getDynamicObjectCollection()).toBeInstanceOf(DynamicObjectCollection);
        expect(dataSource.getDynamicObjectCollection().getObjects().length).toEqual(0);
        expect(dataSource.getIsTimeVarying()).toEqual(false);
    });

    it('Simple Test loading Kml', function() {
        var dataSource = new KmlDataSource();
        var url = 'http://localhost:8080/Apps/CesiumViewer/Gallery/simplePlacemark.kml';

        dataSource.loadUrl(url);
    });

    it('Test loading Kml', function() {
        var dataSource = new KmlDataSource();
        var url = 'http://localhost:8080/Apps/CesiumViewer/Gallery/KML_Samples.kml';

        dataSource.loadUrl(url);
    });
});

Add a new spec to test the simpler placemark


var demand = require('must');

var keystone = require('../').init(),
	Types = keystone.Field.Types;

/** Test List and Fields */

var Test = keystone.List('Test');

Test.add({
	date: Types.Date,
	datetime: Types.Datetime
});

Test.register();

/** Test Item */

var item = new Test.model();

/** FieldType: Date */

describe("Fields", function() {
	describe("Date", function() {

		it('should parse without error via underscore date', function() {
			item._.date.parse('20131204', 'YYYYMMDD');
		});

		it('should be the date we expect', function() {
			demand(item._.date.format()).to.equal('4th Dec 2013');
			demand(item._.date.format('YYYYMMDD')).to.equal('20131204');
		});

		it('should be a moment object', function() {
			demand(item._.date.moment()._isAMomentObject);
		});

	});
});

var demand = require('must');

var keystone = require('../').init(),
	Types = keystone.Field.Types;

/** Test List and Fields */

var Test = keystone.List('Test');
var item;

before(function() {

Test.add({
	date: Types.Date,
	datetime: Types.Datetime,
	bool: Types.Boolean
});

Test.register();
/** Test Item */

item = new Test.model();
});

/** FieldType: Date */

describe("Fields", function() {
	describe("Date", function() {

		it('should parse without error via underscore date', function() {
			item._.date.parse('20131204', 'YYYYMMDD');
		});

		it('should be the date we expect', function() {
			demand(item._.date.format()).to.equal('4th Dec 2013');
			demand(item._.date.format('YYYYMMDD')).to.equal('20131204');
		});

		it('should be a moment object', function() {
			demand(item._.date.moment()._isAMomentObject);
		});

	});
	describe("Boolean", function() {

		it('should update it\'s model if data passed is boolean true', function() {
			Test.fields.bool.updateItem(item, {
				'bool': true
			});
			demand(item.bool).to.be.true();

		});

       		it('should update it\'s  model if data passed is string \'true\'', function() {
			Test.fields.bool.updateItem(item, {
				'bool': 'true'
			});
			demand(item.bool).to.be.true();

		});

	});
});

Add updateItem test for field Boolean.


import * as Rx from 'rxjs';

export const FETCH_USER_PENDING = 'FETCH_USER_PENDING';
export const FETCH_USER_FULFILLED = 'FETCH_USER_FULFILLED';
export const FETCH_USER_ABORTED = 'FETCH_USER_ABORTED';

export const fetchUser = () => (
  (actions, store) => Rx.Observable.of({ id: 1, name: 'Bilbo Baggins', timestamp: new Date() })
    // Delaying to emulate an async request, like Rx.Observable.ajax('/api/path')
    .delay(1000)
    // When our request comes back, we transform it into an action
    // that is then automatically dispatched by the middleware
    .map(
      payload => ({ type: FETCH_USER_FULFILLED, payload })
    )
    // Abort fetching the user if someone dispatches an abort action
    .takeUntil(
      actions.ofType(FETCH_USER_ABORTED)
    )
    // Let's us immediately update the user's state so we can display
    // loading messages to the user, etc.
    .startWith({ type: FETCH_USER_PENDING })
);

// Plain old action
export const abortFetchUser = () => ({ type: FETCH_USER_ABORTED });

import * as Rx from 'rxjs';

export const FETCH_USER_PENDING = 'FETCH_USER_PENDING';
export const FETCH_USER_FULFILLED = 'FETCH_USER_FULFILLED';
export const FETCH_USER_ABORTED = 'FETCH_USER_ABORTED';

export const fetchUser = () => (
  (actions, store) => Rx.Observable.of({ id: 1, name: 'Bilbo Baggins', timestamp: new Date() })
    // Delaying to emulate an async request, like Rx.Observable.ajax('/api/path')
    .delay(1000)
    // When our request comes back, we transform it into an action
    // which the redux-observable middleware will then dispatch
    .map(
      payload => ({ type: FETCH_USER_FULFILLED, payload })
    )
    // Abort fetching the user if someone dispatches an abort action
    .takeUntil(
      actions.ofType(FETCH_USER_ABORTED)
    )
    // Let's us immediately update the user's state so we can display
    // loading messages to the user, etc.
    .startWith({ type: FETCH_USER_PENDING })
);

// Plain old action
export const abortFetchUser = () => ({ type: FETCH_USER_ABORTED });

Reduce confusion about when middleware dispatches emitted actions


var should = require('should'),
    queixinhas_db = require('../lib/db/db');

// Change the default BD configs
queixinhas_db.db_name = 'queixinhas_tests';

describe('MongoDB accesser', function(){
  it('should save, load and remove a document in the database', function(done){
    var value = Date.now();

    queixinhas_db.save('test', {value: value}, function(error, id){

      queixinhas_db.load('test', id, function(error, docs){
        docs[0].value.should.equal(value);

        queixinhas_db.remove('test', id, function(error, docs){

          queixinhas_db.load('test', id, function(error, docs){
            docs.length.should.equal(0);

            done();
          })
        });
      });
    });
  });
});

var should = require('should'),
    queixinhas_db = require('../lib/db/db');

// Change the default BD configs
queixinhas_db.db_name = 'queixinhas_tests';

describe('MongoDB accesser', function(){
  it('should save, load, modify and remove a document in the database', function(done){
    var value = Date.now();

    queixinhas_db.save('test', {value: value}, function(error, id){

      queixinhas_db.load('test', id, function(error, docs){
        docs[0].value.should.equal(value);

        var new_value = Date.now();

        queixinhas_db.update('test', id, {value: new_value}, function(error, doc){
          doc.value.should.equal(new_value);

          queixinhas_db.remove('test', id, function(error, docs){

            queixinhas_db.load('test', id, function(error, docs){
              docs.length.should.equal(0);

              done();
            });
          });
        });
      });
    });
  });
});

Add test to the update method on the DAL


import { context, environment } from 'ember-environment';
import require from 'require';

let jQuery;

if (environment.hasDOM) {
  jQuery = context.imports.jQuery;
  if (!jQuery && typeof require === 'function') {
    jQuery = require('jquery');
  }

  if (jQuery) {
    // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#dndevents
    [
      'dragstart',
      'drag',
      'dragenter',
      'dragleave',
      'dragover',
      'drop',
      'dragend'
    ].forEach(eventName => {
      jQuery.event.fixHooks[eventName] = {
        props: ['dataTransfer']
      };
    });
  }
}

export default jQuery;

import { context, environment } from 'ember-environment';
import require from 'require';

let jQuery;

if (environment.hasDOM) {
  jQuery = context.imports.jQuery;
  if (!jQuery && typeof require === 'function') {
    jQuery = require('jquery');
  }

  if (jQuery) {
    if (jQuery.event.addProp) {
      jQuery.event.addProp('dataTransfer');
    } else {
      // http://www.whatwg.org/specs/web-apps/current-work/multipage/dnd.html#dndevents
      [
        'dragstart',
        'drag',
        'dragenter',
        'dragleave',
        'dragover',
        'drop',
        'dragend'
      ].forEach(eventName => {
        jQuery.event.fixHooks[eventName] = {
          props: ['dataTransfer']
        };
      });
    }
  }
}

export default jQuery;

Use `jQuery.event.addProp` to add `dataTransfer` property


import Promise from "bluebird";
import gpio from "rpi-gpio";
import _ from "underscore";

class RpiGpioOpener {

  constructor(config) {
    gpio.setMode(gpio.MODE_BCM);
    this.pins = config.pins;
    this.opening = {};
  }

  canOpen(doorId) {
    return !_.isUndefined(this.pins[doorId]);
  }

  open(doorId, time) {
    if (_.isUndefined(this.pins[doorId]) || this.opening[doorId]) return;

    this.opening[doorId] = true;
    this.writePin(doorId, true)
      .delay(time)
      .then(() => this.writePin(doorId, false))
      .catch(console.error)
      .finally(() => this.opening[doorId] = false);
  }

  writePin(doorId, value) {
    const pin = this.pins[doorId];
    const gpioSetup = Promise.promisify(gpio.setup, { context: gpio });
    const gpioWrite = Promise.promisify(gpio.write, { context: gpio });

    return gpioSetup(pin, gpio.DIR_OUT, gpio.EDGE_NONE)
      .tap(() => console.log(`Writing '${value}' to pin ${pin}`))
      .then(() => gpioWrite(pin, value));
  }
}

export default RpiGpioOpener;

import Promise from "bluebird";
import gpio from "rpi-gpio";
import _ from "underscore";

class RpiGpioOpener {

  constructor(config) {
    gpio.setMode(gpio.MODE_BCM);
    this.pins = config.pins;
    this.opening = {};
  }

  canOpen(doorId) {
    return !_.isUndefined(this.pins[doorId]);
  }

  open(doorId, time) {
    if (!this.canOpen(doorId) || this.opening[doorId]) return;

    this.opening[doorId] = true;
    this.writePin(doorId, true)
      .delay(time)
      .then(() => this.writePin(doorId, false))
      .catch(console.error)
      .finally(() => this.opening[doorId] = false);
  }

  writePin(doorId, value) {
    const pin = this.pins[doorId];
    const gpioSetup = Promise.promisify(gpio.setup, { context: gpio });
    const gpioWrite = Promise.promisify(gpio.write, { context: gpio });

    return gpioSetup(pin, gpio.DIR_OUT, gpio.EDGE_NONE)
      .tap(() => console.log(`Writing '${value}' to pin ${pin}`))
      .then(() => gpioWrite(pin, value));
  }
}

export default RpiGpioOpener;

Use `canOpen` in GPIO `open` function


const fs       = require('fs')
const path     = require('path')
const {name}   = require('./package.json')
const requireg = require('requireg')

module.exports = (job, settings, { input, provider, params }, type) => {
    if (type != 'postrender') {
        throw new Error(`Action ${name} can be only run in postrender mode, you provided: ${type}.`)
    }

    if (!provider) {
        throw new Error(`Provider is missing.`)
    }

    /* check if input has been provided */
    input = input || job.output;

    /* fill absolute/relative paths */
    if (!path.isAbsolute(input)) input = path.join(job.workpath, input);

    settings.logger.log(`[${job.uid}] starting action-upload action`)

    try {
        return requireg('@nexrender/provider-' + provider).upload(job, settings, input, params || {});
    } catch (e) {
        if (e.message.indexOf('Could not require module') !== -1) {
            return Promise.reject(new Error(`Couldn\'t find module @nexrender/provider-${provider}, Unknown provider given.`))
        }

        throw e;
    }
}

const fs       = require('fs')
const path     = require('path')
const {name}   = require('./package.json')
const requireg = require('requireg')

module.exports = (job, settings, { input, provider, params }, type) => {
    if (type != 'postrender') {
        throw new Error(`Action ${name} can be only run in postrender mode, you provided: ${type}.`)
    }

    if (!provider) {
        throw new Error(`Provider is missing.`)
    }

    /* check if input has been provided */
    input = input || job.output;

    /* fill absolute/relative paths */
    if (!path.isAbsolute(input)) input = path.join(job.workpath, input);

    settings.logger.log(`[${job.uid}] starting action-upload action`)

    let requirePackage = ''
    try {
        /* try requiring official providers */
        requirePackage = `@nexrender/provider-${provider}`
        return requireg('@nexrender/provider-' + provider).upload(job, settings, input, params || {});

    } catch (e) {
        if (e.message.indexOf('Could not require module') !== -1) {
            try{
                /* try requiring custom providers */
                requirePackage = provider
                return requireg(provider).upload(job, settings, input, params || {});

            } catch(e) {
                if (e.message.indexOf('Could not require module') !== -1) {
                    return Promise.reject(new Error(`Couldn\'t find module ${requirePackage}, Unknown provider given.`))
                }

                throw e;
            }
        }

        throw e;
    }
}

Enable globally installed custom upload action


// Copyright 2014, Renasar Technologies Inc.
/* jshint: node:true */

'use strict';

var di = require('di');

module.exports = eventsProtocolFactory;

di.annotate(eventsProtocolFactory, new di.Provide('Protocol.Events'));
di.annotate(eventsProtocolFactory,
    new di.Inject(
        'Services.Messenger',
        'Protocol.Exchanges.Events',
        'Assert'
    )
);

function eventsProtocolFactory (messenger, eventsExchange, assert) {
    function EventsProtocol () {
    }

    EventsProtocol.prototype.publishTftpSuccess = function (nodeId, data) {
        assert.ok(nodeId);
        assert.object(data);

        messenger.publish(
            eventsExchange.exchange,
            'tftp.success' + '.' + nodeId,
            data
        );
    };

    EventsProtocol.prototype.publishTftpFailure = function (nodeId, data) {
        assert.ok(nodeId);
        assert.object(data);

        messenger.publish(
            eventsExchange.exchange,
            'tftp.failure' + '.' + nodeId,
            data
        );
    };

    EventsProtocol.prototype.publishHttpResponse = function (nodeId, data) {
        assert.ok(nodeId);
        assert.object(data);

        messenger.publish(
            eventsExchange.exchange,
            'http.response' + '.' + nodeId,
            data
        );
    };

    return new EventsProtocol();
}

// Copyright 2014, Renasar Technologies Inc.
/* jshint: node:true */

'use strict';

var di = require('di');

module.exports = eventsProtocolFactory;

di.annotate(eventsProtocolFactory, new di.Provide('Protocol.Events'));
di.annotate(eventsProtocolFactory,
    new di.Inject(
        'Services.Messenger',
        'Protocol.Exchanges.Events',
        'Assert'
    )
);

function eventsProtocolFactory (messenger, eventsExchange, assert) {
    function EventsProtocol () {
    }

    EventsProtocol.prototype.publishTftpSuccess = function (nodeId, data) {
        assert.ok(nodeId);
        assert.object(data);

        messenger.publish(
            eventsExchange.exchange,
            'tftp.success' + '.' + nodeId,
            data
        );
    };

    EventsProtocol.prototype.publishTftpFailure = function (nodeId, data) {
        assert.ok(nodeId);
        assert.object(data);

        messenger.publish(
            eventsExchange.exchange,
            'tftp.failure' + '.' + nodeId,
            data
        );
    };

    EventsProtocol.prototype.publishHttpResponse = function (nodeId, data) {
        assert.ok(nodeId);
        assert.object(data);

        messenger.publish(
            eventsExchange.exchange,
            'http.response' + '.' + nodeId,
            data
        );
    };

    EventsProtocol.prototype.publishDhcpBoundLease = function(nodeId, data) {
        assert.ok(nodeId);
        assert.ok(data);

        messenger.publish(
            eventsExchange.exchange,
            'dhcp.bind.success' + '.' + nodeId,
            data
        );
    };

    return new EventsProtocol();
}

Add DHCP lease binding to the protocol


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

require("babel/register");

var EventEmitter = require('eventemitter3');
var emitter = new EventEmitter();

var rx = function(req, res) {
  var data = req.body;
  emitter.emit('pkg', data);
  res.end();
};

var tx = function(req, res) {
  res.writeHead(200, {
    'Content-Type':   'text/event-stream',
    'Cache-Control':  'no-cache',
    'Connection':     'keep-alive'
  });

  // Heartbeat
  var nln = () => res.write('\n');
  var hbt = setInterval(nln, 15000);

  var onPkg = (data) => {
    res.write("retry: 500\n");
    res.write(`event: pkg\n`);
    res.write(`data: ${JSON.stringify(data)}\n\n`);
  };

  emitter.on('pkg', onPkg);

  // Clear heartbeat and listener
  req.on('close', () => {
    clearInterval(hbt);
    emitter.removeListener('pkg', onPkg);
  });
};

module.exports = {
  rx: rx,
  tx: tx
};

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

require("babel/register");

var EventEmitter = require('eventemitter3');
var emitter = new EventEmitter();

var rx = function(req, res) {
  if(req.query.api_key === process.env.API_KEY){
    var data = req.body;
    emitter.emit('pkg', data);
  }
  res.end();
};

var tx = function(req, res) {
  res.writeHead(200, {
    'Content-Type':   'text/event-stream',
    'Cache-Control':  'no-cache',
    'Connection':     'keep-alive'
  });

  // Heartbeat
  var nln = () => res.write('\n');
  var hbt = setInterval(nln, 15000);

  var onPkg = (data) => {
    res.write("retry: 500\n");
    res.write(`event: pkg\n`);
    res.write(`data: ${JSON.stringify(data)}\n\n`);
  };

  emitter.on('pkg', onPkg);

  // Clear heartbeat and listener
  req.on('close', () => {
    clearInterval(hbt);
    emitter.removeListener('pkg', onPkg);
  });
};

module.exports = {
  rx: rx,
  tx: tx
};

Add protection via API_KEY in parameter


'use strict';

var Backbone = require('backbone');
var $ = require('jquery');
Backbone.$ = $;

var BusinessCollection = require('../collections/business-collection');
var MapModel = require('../models/map-model');

module.exports = function() {
	this.mapModel = new MapModel();
	this.collection = new BusinessCollection({
		radius_filter: 500
	});

	var InitView = require('../views/init-view');
	var initView = new InitView({model: this.mapModel, collection: this.collection});
	$('#backbone').html(initView.$el);
};

'use strict';

var Backbone = require('backbone');
var $ = require('jquery');
Backbone.$ = $;

var BusinessCollection = require('../collections/business-collection');
var MapModel = require('../models/map-model');

module.exports = function() {
	this.mapModel = new MapModel();
	this.collection = new BusinessCollection({
		radius_filter: 100
	});

	var InitView = require('../views/init-view');
	var initView = new InitView({model: this.mapModel, collection: this.collection});
	$('#backbone').html(initView.$el);
};

Set a tight search radius


var isbin = require('isbin');
var logger = require('chip')();
var prequire = require('parent-require');

module.exports = function(launchPhantom){
	'use strict';

	isbin('phantomjs', function(exists) {
		if (!exists){
			try{
				launchPhantom(prequire('phantomjs').path);
			} catch(e){
				var npm = require('npm');
				npm.load(npm.config, function (err) {
					if (err) { logger.error(err); }
					npm.commands.install(['phantomjs'], function (err) {
						if (err) { logger.error(err); }
						launchPhantom(prequire('phantomjs').path);
					});
					npm.on('log', function (message) {
						logger.info(message);
					});
				});
			}
		} else {
			launchPhantom();
		}
	});
};

var isbin = require('isbin');
var logger = require('chip')();
var prequire = require('parent-require');

module.exports = function(launchPhantom){
	'use strict';

	isbin('phantomjs', function(exists) {
		if (!exists){
			try{
				launchPhantom(prequire('phantomjs').path);
			} catch(e){
				var npm = require('npm');
				npm.load(npm.config, function (err) {
					if (err) { logger.error(err); }
					npm.commands.install(['phantomjs@1.9.19'], function (err) {
						if (err) { logger.error(err); }
						launchPhantom(prequire('phantomjs').path);
					});
					npm.on('log', function (message) {
						logger.info(message);
					});
				});
			}
		} else {
			launchPhantom();
		}
	});
};

Set the version 1.9 of phantomjs as the 2 is not compatible yet


$(document).ready(function(){
  var pairing_duration_ms;
  console.log("Loading...")
  $('button.duration-button').on('click', function(event){
    event.preventDefault();
    console.log($('input.duration').val());
    if($('input.duration').val() !== "" ){
      pairing_duration_ms = parseInt($('input.duration').val()) * 6000;
      console.log(pairing_duration_ms)
    } else {
      alert("Please Enter A Number")
    }
  });

  $('button.start-pairing').on('click', function(){
    setTimeout(function(){
      alert('Time to Switch It ^');
    }, pairing_duration_ms);
  });
});

$(document).ready(function(){
  var pairing_duration_ms;

  $('button.duration-button').on('click', function(event){
    event.preventDefault();

    if($('input.duration').val() !== "" ){
      pairing_duration_ms = parseInt( $('input.duration').val() ) * 6000;
    } else {
      alert("Please Enter A Number");
    }
  });

  $('button.start-pairing').on('click', function(){
    setTimeout(function(){
      alert('Time to Switch It ^');
    }, pairing_duration_ms);
  });
});

Clean up Test Code in Popup JS


TC.control = TC.control || {};

if (!TC.Control) {
    TC.syncLoadJS(TC.apiLocation + 'TC/Control');
}

TC.control.NavBarHome = function () {
    TC.Control.apply(this, arguments);
};

TC.inherit(TC.control.NavBarHome, TC.Control);

(function () {
    var ctlProto = TC.control.NavBarHome.prototype;

    ctlProto.CLASS = 'tc-ctl-nav-home';

    ctlProto.render = function () {
        var self = this;
        if (!self.wrap) {
            self.wrap = new TC.wrap.control.NavBarHome(self);
        }
        return Promise.resolve();
    };

    ctlProto.register = function (map) {
        const self = this;
        const result = TC.Control.prototype.register.call(self, map);
        self.wrap.register(map);

        map.on(TC.Consts.event.PROJECTIONCHANGE, function (e) {
            const crs = e.crs;
            var bottomLeft = TC.Util.reproject([map.options.initialExtent[0], map.options.initialExtent[1]], map.options.crs, crs);
            var topRight = TC.Util.reproject([map.options.initialExtent[2], map.options.initialExtent[3]], map.options.crs, crs);
            self.wrap.setInitialExtent([bottomLeft[0], bottomLeft[1], topRight[0], topRight[1]]);
        });

        return result;
    };

})();

TC.control = TC.control || {};

if (!TC.Control) {
    TC.syncLoadJS(TC.apiLocation + 'TC/Control');
}

TC.control.NavBarHome = function () {
    TC.Control.apply(this, arguments);
};

TC.inherit(TC.control.NavBarHome, TC.Control);

(function () {
    var ctlProto = TC.control.NavBarHome.prototype;

    ctlProto.CLASS = 'tc-ctl-nav-home';

    ctlProto.render = function () {
        var self = this;
        if (!self.wrap) {
            self.wrap = new TC.wrap.control.NavBarHome(self);
        }
        return Promise.resolve();
    };

    ctlProto.register = function (map) {
        const self = this;
        const result = TC.Control.prototype.register.call(self, map);
        self.wrap.register(map);

        map.on(TC.Consts.event.PROJECTIONCHANGE, function (e) {
            const crs = e.newCrs;
            var bottomLeft = TC.Util.reproject([map.options.initialExtent[0], map.options.initialExtent[1]], map.options.crs, crs);
            var topRight = TC.Util.reproject([map.options.initialExtent[2], map.options.initialExtent[3]], map.options.crs, crs);
            self.wrap.setInitialExtent([bottomLeft[0], bottomLeft[1], topRight[0], topRight[1]]);
        });

        return result;
    };

})();

Use new PROJECTIONCHANGE event properties


'use strict';

var toUint = require('es5-ext/lib/Number/to-uint')

  , count = 0, limit = Infinity, callbacks = [];

exports.open = function () {
	++count;
};
exports.close = function () {
	if ((--count < limit) && callbacks.length) {
		do {
			callbacks.shift()();
		} while ((count < limit) && callbacks.length);
	}
};

require('child_process').exec('ulimit -n', { env: process.env },
	function (err, stdout, stderr) {
		if (!stdout) {
			return;
		}
		stdout = stdout.trim();
		if (isNaN(stdout)) {
			return;
		}
		// We subtract 25 to give eventual outer processes some air
		limit = Number(stdout) - 25;
	});

exports.isAvailable = function (padding) {
	return count < (limit - toUint(padding));
};

exports.cb = function (cb) {
	if (count < limit) {
		cb();
		return;
	}
	callbacks.push(cb);
};

'use strict';

var toUint = require('es5-ext/lib/Number/to-uint')

  , count = 0, limit = Infinity, callbacks = [];

exports.open = function () {
	++count;
};
exports.close = function () {
	if ((--count < limit) && callbacks.length) {
		do {
			callbacks.shift()();
		} while ((count < limit) && callbacks.length);
	}
};

require('child_process').exec('ulimit -n', { env: process.env },
	function (err, stdout, stderr) {
		if (!stdout) {
			return;
		}
		stdout = stdout.trim();
		if (isNaN(stdout)) {
			return;
		}
		// We subtract 25 to give eventual outer processes some air
		limit = Math.max(Number(stdout) - 25, 5);
	});

exports.isAvailable = function (padding) {
	return count < (limit - toUint(padding));
};

exports.cb = function (cb) {
	if (count < limit) {
		cb();
		return;
	}
	callbacks.push(cb);
};

Allow at least 5 descriptors if detection goes wrong


/**
 * Migrates the database from one version to another.
 */
function migrateStorage() {
	var extensionVersion = getExtensionVersion().major;

	getStorageVersion(function(storageVersion) {
		if (extensionVersion != storageVersion) {
			console.log("Extension and storage versions are not equal", extensionVersion, storageVersion);
			setStorageVersion(extensionVersion);

			if (storageVersion == 1) {
				if (extensionVersion.major == 2) {
					// Migrate from a database from 1.x.x to 2.x.x
					migrate_1_to_2(function() {
						console.log("Migration from 1.x.x to 2.x.x complete");
					});
				}
			}
		}
	});
}

/**
 * Migrates the database from one version to another.
 */
function migrateStorage() {
	var extensionVersion = getExtensionVersion().major;

	getStorageVersion(function(storageVersion) {
		if (extensionVersion != storageVersion) {
			console.log("Extension and storage versions are not equal", extensionVersion, storageVersion);
			setStorageVersion(extensionVersion);

			if (storageVersion == 1) {
				if (extensionVersion == 2) {
					// Migrate from a database from 1.x.x to 2.x.x
					migrate_1_to_2(function() {
						console.log("Migration from 1.x.x to 2.x.x complete");
					});
				}
			}
		}
	});
}

Fix version check for extension version.


"use strict";

var interpolate = require("./interpolate");
var format = require("./format");
var reduce = require("@sinonjs/commons").prototypes.array.reduce;

function prepareMessage(message) {
    if (!message) {
        return "";
    }
    return message + (/[.:!?]$/.test(message) ? " " : ": ");
}

function interpolateProperties(referee, message, properties) {
    return reduce(
        Object.keys(properties),
        function(str, name) {
            var formattedValue =
                name === "customMessage"
                    ? prepareMessage(properties[name])
                    : format(properties[name]);
            return interpolate(str, name, formattedValue);
        },
        message || ""
    );
}

module.exports = interpolateProperties;

"use strict";

var interpolate = require("./interpolate");
var format = require("./format");
var reduce = require("@sinonjs/commons").prototypes.array.reduce;

function prepareMessage(message) {
    if (!message) {
        return "";
    }
    return message + (/[.:!?]$/.test(message) ? " " : ": ");
}

function interpolateProperties(referee, message, properties) {
    return reduce(
        Object.keys(properties),
        function(str, name) {
            var formattedValue =
                name === "customMessage"
                    ? prepareMessage(properties[name])
                    : format(properties[name]);
            return interpolate(str, name, formattedValue);
        },
        message
    );
}

module.exports = interpolateProperties;

Improve test coverage of interpolateProperties


(function(GOVUK, Modules) {
  "use strict";

  GOVUK.timeCache = {};
  GOVUK.resultCache = {};

  var dd = new diffDOM();

  let getter = function(resource, interval, render) {

    if (
      GOVUK.resultCache[resource] &&
      (Date.now() < GOVUK.timeCache[resource])
    ) {
      render(GOVUK.resultCache[resource]);
    } else {
      GOVUK.timeCache[resource] = Date.now() + interval;
      $.get(
        resource,
        response => render(GOVUK.resultCache[resource] = response)
      );
    }

  };

  let poller = (resource, key, $component, interval) => () => getter(
    resource, interval, response => dd.apply(
      $component.get(0),
      dd.diff($component.get(0), $(response[key]).get(0))
    )
  );

  Modules.UpdateContent = function() {

    this.start = function(component) {

      const $component = $(component);
      interval = ($(component).data("interval-seconds") * 1000) || 1500;

      setInterval(
        poller($component.data('resource'), $component.data('key'), $component, interval),
        interval / 5
      );

    };
  };

})(window.GOVUK, window.GOVUK.Modules);

(function(Modules) {
  "use strict";

  var queues = {};
  var dd = new diffDOM();

  var getRenderer = $component => response => dd.apply(
    $component.get(0),
    dd.diff($component.get(0), $(response[$component.data('key')]).get(0))
  );

  var getQueue = resource => (
    queues[resource] = queues[resource] || []
  );

  var flushQueue = function(queue, response) {
    while(queue.length) queue.shift()(response);
  };

  var poll = function(renderer, resource, queue, interval) {

    if (queue.push(renderer) === 1) $.get(
      resource,
      response => flushQueue(queue, response)
    );

    setTimeout(
      () => poll(...arguments), interval
    );

  };

  Modules.UpdateContent = function() {

    this.start = component => poll(
      getRenderer($(component)),
      $(component).data('resource'),
      getQueue($(component).data('resource')),
      ($(component).data('interval-seconds') || 1.5) * 1000
    );

  };

})(window.GOVUK.Modules);

Stop AJAX updates queuing requests


var TC = require('tangram.cartodb');
var LeafletLayerView = require('./leaflet-layer-view');
var L = require('leaflet');

var LeafletCartoDBVectorLayerGroupView = L.Layer.extend({
  includes: [
    LeafletLayerView.prototype
  ],

  options: {
    minZoom: 0,
    maxZoom: 28,
    tileSize: 256,
    zoomOffset: 0,
    tileBuffer: 50
  },

  events: {
    featureOver: null,
    featureOut: null,
    featureClick: null
  },

  initialize: function (layerGroupModel, map) {
    LeafletLayerView.call(this, layerGroupModel, this, map);
    layerGroupModel.bind('change:urls', this._onURLsChanged, this);

    this.tangram = new TC(map);

    layerGroupModel.each(this._onLayerAdded, this);
    layerGroupModel.onLayerAdded(this._onLayerAdded.bind(this));
  },

  onAdd: function (map) {
    L.Layer.prototype.onAdd.call(this, map);
  },

  _onLayerAdded: function (layer) {
    var self = this;
    layer.bind('change:meta', function (e) {
      self.tangram.addLayer(e.attributes);
    });
  },

  _onURLsChanged: function (e, res) {
    this.tangram.addDataSource(res.tiles[0]);
  }
});

module.exports = LeafletCartoDBVectorLayerGroupView;

var TC = require('tangram.cartodb');
var LeafletLayerView = require('./leaflet-layer-view');
var L = require('leaflet');

var LeafletCartoDBVectorLayerGroupView = L.Class.extend({
  includes: [
    LeafletLayerView.prototype
  ],

  options: {
    minZoom: 0,
    maxZoom: 28,
    tileSize: 256,
    zoomOffset: 0,
    tileBuffer: 50
  },

  events: {
    featureOver: null,
    featureOut: null,
    featureClick: null
  },

  initialize: function (layerGroupModel, map) {
    LeafletLayerView.call(this, layerGroupModel, this, map);
    layerGroupModel.bind('change:urls', this._onURLsChanged, this);

    this.tangram = new TC(map);

    layerGroupModel.each(this._onLayerAdded, this);
    layerGroupModel.onLayerAdded(this._onLayerAdded.bind(this));
  },

  onAdd: function (map) {
    L.Layer.prototype.onAdd.call(this, map);
  },

  _onLayerAdded: function (layer) {
    var self = this;
    layer.bind('change:meta', function (e) {
      self.tangram.addLayer(e.attributes);
    });
  },

  setZIndex: function (zIndex) {},

  _onURLsChanged: function (e, res) {
    this.tangram.addDataSource(res.tiles[0]);
  }
});

module.exports = LeafletCartoDBVectorLayerGroupView;

Change for L.Class and add zombie function


'use strict';

/* global CartUtility */
module.exports = function($scope, $location, $anchorScroll, $dataService, $editorService) {
    CartUtility.log('CartBlogNewCtrl');

    $scope.aceEditor = $editorService.createEditor('markdown-edit', 'markdown-preview', CartUtility.getPureAbsUrlFromLocation($location));

    $scope.toggleToc = CartUtility.toggleToc;

    $scope.$on('$routeChangeStart', function() {
        CartUtility.log('CartBlogNewCtrl $routeChangeStart entered!');
        // anchor link logic
        var prevHash = $location.hash();
        if (typeof prevHash === 'string' && prevHash !== '') {
            $location.hash(CartUtility.escapeAnchorName(prevHash));
            $anchorScroll();
            $location.hash(prevHash);
        }
    });
};

'use strict';

/* global CartUtility */
module.exports = function($scope, $location, $anchorScroll, $routeParams, $dataService, $editorService) {
    CartUtility.log('CartBlogNewCtrl');

    $scope.aceEditor = $editorService.createEditor('markdown-edit', 'markdown-preview', $routeParams.postId, CartUtility.getPureAbsUrlFromLocation($location));

    $scope.toggleToc = CartUtility.toggleToc;

    $scope.$on('$routeChangeStart', function() {
        CartUtility.log('CartBlogNewCtrl $routeChangeStart entered!');
        // anchor link logic
        var prevHash = $location.hash();
        if (typeof prevHash === 'string' && prevHash !== '') {
            $location.hash(CartUtility.escapeAnchorName(prevHash));
            $anchorScroll();
            $location.hash(prevHash);
        }
    });
};

Load post id from route params, and create editor with it.


var imgs = document.querySelectorAll('img.avatar');

if (imgs) {
  imgs.forEach(function(e) {
    e.addEventListener('error', defaultAvatar(e));
  });
}

function defaultAvatar(e) {
  e.onerror = null;
  e.src = k.STATIC_URL + 'sumo/img/avatar.png';
}

var imgs = document.querySelectorAll('img.avatar');

if (imgs) {
  imgs.forEach(function(e) {
    e.addEventListener('error', defaultAvatar);
  });
}

function defaultAvatar() {
  this.onerror = null;
  this.src = k.STATIC_URL + 'sumo/img/avatar.png';
}

Handle avatar if image is missing.


'use strict';

function notEmpty(src) {
    return !!src;
}

module.exports = [{
    type:    'input',
    name:    'name',
    message: 'Project Name',
    validate: notEmpty
}, {
    type:     'input',
    name:     'description',
    message:  'Description',
    validate: notEmpty
}, {
    type: 'list',
    name: 'engine',
    message: 'Which templating engine?',
    choices: [{
        name:  'Handlebars',
        value: 'handlebars'
    }, {
        name:  'DustJS',
        value: 'dust'
    }],
    default: 'handlebars'
}, {
    type:    'list',
    name:    'grid',
    message: 'Which grid system?',
    choices: [{
        name:  'Bootstrap',
        value: 'bootstrap'
    }, {
        name:  'Susy',
        value: 'susy'
    }]
}];

'use strict';

function notEmpty(src) {
    return !!src;
}

module.exports = [{
    type:    'input',
    name:    'name',
    message: 'Project Name',
    validate: notEmpty
}, {
    type:     'input',
    name:     'description',
    message:  'Description',
    validate: notEmpty
}, {
    type: 'list',
    name: 'engine',
    message: 'Which templating engine?',
    choices: [{
        name:  'Handlebars',
        value: 'handlebars'
    }, {
        name:  'DustJS',
        value: 'dust'
    }],
    default: 'handlebars'
}, {
    type:    'list',
    name:    'grid',
    message: 'Which grid system?',
    choices: [{
        name:  'Bootstrap',
        value: 'bootstrap'
    }, {
        name:  'Susy',
        value: 'susy'
    }],
    default: 'bootstrap'
}];

Add default grid system prompt


import Component from '@ember/component';
import { inject as service } from '@ember/service';
import { computed, get, set } from '@ember/object';
import layout from './template';

export default Component.extend({
  layout,

  scope: service(),

  fullColspan: null,
  afterName: 0,
  showState: false,
  afterState: 0,
  alignState: 'text-center',
  showActions: true,

  nodes: null,
  nodeId: null,
  tagName: '',

  didReceiveAttrs() {
    const nodes = get(this, 'nodes');
    const nodeId = get(this, 'nodeId');
    if (nodes && nodeId) {
      const clusterId = get(this, 'scope.currentCluster.id');
      const targetNode = nodes.find(n => n.id === nodeId && n.clusterId === clusterId);
      set(this, 'model', targetNode);
    }
  },
});

import Component from '@ember/component';
import { inject as service } from '@ember/service';
import { computed, get, set } from '@ember/object';
import layout from './template';

export default Component.extend({
  layout,

  scope: service(),

  fullColspan: null,
  afterName: 0,
  showState: false,
  afterState: 0,
  alignState: 'text-center',
  showActions: true,
  nameSpan: null,

  nodes: null,
  nodeId: null,
  tagName: '',

  didReceiveAttrs() {
    const nodes = get(this, 'nodes');
    const nodeId = get(this, 'nodeId');
    if (nodes && nodeId) {
      const clusterId = get(this, 'scope.currentCluster.id');
      const targetNode = nodes.find(n => n.id === nodeId && n.clusterId === clusterId);
      set(this, 'model', targetNode);
    }

    const nameSpan = get(this,'fullColspan') -
      ( get(this, 'afterName') ? 1 : 0 ) -
      ( get(this, 'showState') ? 1 : 0 ) -
      ( get(this, 'afterState') ? 1 : 0 ) -
      ( get(this, 'showActions') ? 1 : 0 );

    set(this, 'nameSpan', nameSpan);
  },
});

Fix group by style issue


Template.dashboardCounts.created = function () {
    this.subscribe("linensCount");
};

Template.dashboardCounts.helpers({
    'linensCount': function () {
        // Return the linens count
        return linensCount = Counts.get('linensCount');
    }
});

Template.dashboardCounts.created = function () {
    this.subscribe("linensCount");
    this.subscribe("jymCount");
    this.subscribe("yafCount");
};

Template.dashboardCounts.helpers({
    'linensCount': function () {
        // Return the linens count
        return Counts.get('linensCount');
    },
    'jymCount': function () {
        // Return the linens count
        return Counts.get('jymCount');
    },
    'yafCount': function () {
        // Return the linens count
        return Counts.get('yafCount');
    }
});

Add jymCount and yafCount helpers; cleanup


'use strict';
module.exports = {
  up: function(queryInterface, Sequelize) {
    return queryInterface.createTable('bookmarks', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      repo_id: {
        type: Sequelize.INTEGER
      },
      created_at: {
        allowNull: false,
        type: Sequelize.DATE
      },
      updated_at: {
        allowNull: false,
        type: Sequelize.DATE
      }
    });
  },
  down: function(queryInterface, Sequelize) {
    return queryInterface.dropTable('bookmarks');
  }
};

'use strict';
module.exports = {
  up: function(queryInterface, Sequelize) {
    return queryInterface.createTable('bookmarks', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      repo_id: {
        type: Sequelize.INTEGER,
        unique: true,
      },
      created_at: {
        allowNull: false,
        type: Sequelize.DATE,
      },
      updated_at: {
        allowNull: false,
        type: Sequelize.DATE,
      }
    });
  },
  down: function(queryInterface, Sequelize) {
    return queryInterface.dropTable('bookmarks');
  }
};

Fix code style and change repo_id as unique field.


module.exports = function (message, callback) {
  var interrupted = false;
  var signal = process.platform.indexOf('win') >= 0 ? "exit" : "SIGINT";
  process.on(signal, function () {
    if (interrupted) {
      process.exit();
    }
    console.log(message + " Interrupt a second time to quit");
    interrupted = true;
    setTimeout(function () {
      interrupted = false;
      callback();
    }, 1500);
  });
};

module.exports = function (message, callback) {
  var interrupted = false;
  var signal = process.platform === "win32" ? "exit" : "SIGINT";
  process.on(signal, function () {
    if (interrupted) {
      process.exit();
    }
    console.log(message + " Interrupt a second time to quit");
    interrupted = true;
    setTimeout(function () {
      interrupted = false;
      callback();
    }, 1500);
  });
};

Fix interrupt on OS X


'use strict';

var Hapi = require('hapi'),
		config = require('./config'),
		indexRoutes = require('./src/api/index/indexRoutes');

var options = {
	cors: true,
	cache: {
		engine: 'redis',
		partition: 'cm'
	}
};

var server = Hapi.createServer('0.0.0.0', config.port, options);
<% if (!!npmDependencies.flod) {%>
var Flod = require('flod');
var probe = new Flod.Probe(server, {server: 'hapi', version: '<%= npmDependencies.hapi%>'});
<%}%>

server.route(indexRoutes);

server.start();
console.log('Hapi server running in port ' + config.port);

module.exports = server;

'use strict';

var Hapi = require('hapi');
var config = require('./config');
var indexRoutes = require('./src/api/index/indexRoutes');
//mk:require

var options = {
	cors: true,
	cache: {
		engine: 'redis',
		partition: 'cm'
	}
};

var server = Hapi.createServer('0.0.0.0', config.port, options);
<% if (!!npmDependencies.flod) {%>
var Flod = require('flod');
var probe = new Flod.Probe(server, {server: 'hapi', version: '<%= npmDependencies.hapi%>'});
<%}%>

server.route(indexRoutes);
//mk:route

server.start();
console.log('Hapi server running in port ' + config.port);

module.exports = server;

Update server.js in hapi generator for the hapi-util


/**
 * @return {string}
 * @public
 */
Object.prototype.toString = function() {
  return window.String(this.$javaToString());
};

/**
 * @override
 * @return {string}
 * @public
 */
Object.prototype.toString = function() {
  return window.String(this.$javaToString());
};

Add @override annotation to Object.toString.


var board = [
  [],
  [],
  [],
  [],
  [],
  [],
  []
]

// Click on column
//jquery will know that you clicked on a specific column
//CSS will provide links for the specific columns
//(#:id).on('click', function(){
// board.(this.attr[:id])
// })

// add turn counter
// How to know we've won
// everytime a piece is placed we need to run a JS function to check for connect 4
// check for 4 in a column (easy)
//  - for loop : 0 index -> 2nd index
//      check next three values, if all are the same, return won
//       (only check the column that was clicked on)
// check for 4 in a row (harder)
//  - for loop: look at the row in which the piece lands, and right and left
//  - recursion? base cases 1) color doesnt' match, 2) there are 4 in a row
//  -   needs to look to the right and left (target column -1 or + 1) of the placed piece (or until it reaches the edge of the board)
//  - while loop? While there are matching colors || there aren' 4 in a row || you haven't hit the edge keep looking
// check for 4 diagonal (tricky)
//  - from every piece placed, look over one, up one, recursion(see if we can kick it's ass)
//        - base cases 1) color doesn't match
//        -            2)there are 4 in a row
//  - for every piece placaed, look down one over one.

Set up board and pseudocode logic


define(function () {
	'use strict';

	function getRequest(data) {
		var xhr =  new ('onload' in new XMLHttpRequest()) XMLHttpRequest : XDomainRequest,
			baseUrl = 'https://www.google.com.ua/search?q=',
			tailUrl = '&tbm=isch';

		xhr.open('GET', baseUrl + encodeURIComponent(data) + tailUrl, true);

		xhr.send();

		xhr.onreadystatechange = function () {
			if (xhr.readyState !== 4) {
				return;
			}

			if (xhr.status !== 200) {
				console.log(xhr.status, ': ', xhr.statusText);
			} else {
				console.log(xhr.responseText);
			}
		};
	}

	/**
	 *	@exports
	 */
	return {
		getRequest: getRequest
	};
});

define(function () {
	'use strict';

	function getRequest(data) {
		var xhr =  new ('onload' in new XMLHttpRequest() ? XMLHttpRequest : XDomainRequest),
			baseUrl = 'https://ajax.googleapis.com/ajax/services/search/images?v=1.0&q=';

		xhr.open('GET', baseUrl + encodeURIComponent(data), true);

		xhr.send();

		xhr.onload = function () {
			console.log(xhr.responseText);
		};
	}

	/**
	 *	@exports
	 */
	return {
		getRequest: getRequest
	};
});

Fix syntax error in AJAX interface detection.


/*
// Validation is currently broken in 5.7
var JPAudioPlayerBlock = {
	validate:function(){
		var failed=0;
		if ($("#audioBlock-singleAudio input[name=fID]").val() <= 0) {
			alert(ccm_t('choose-file'));
			failed = 1;
		}
		if(failed){
			ccm_isBlockError=1;
			return false;
		}
		return true;
	}
}

ccmValidateBlockForm = function() { return JPAudioPlayerBlock.validate(); }
*/

Add note about block validation.


const feathersErrors = require('@feathersjs/errors');

const errors = feathersErrors.errors;

module.exports = function (...providers) {
  return context => {
    const hookProvider = (context.params || {}).provider;

    const anyProvider = providers.length === 0;
    const thisProvider = providers.some(provider =>
      provider === hookProvider ||
      (provider === 'server' && !hookProvider) ||
      (provider === 'external' && !!hookProvider)
    );

    if (anyProvider || thisProvider) {
      throw new errors.MethodNotAllowed(
        `Provider '${context.params.provider}' can not call '${context.method}'. (disallow)`
      );
    }
  };
};

const feathersErrors = require('@feathersjs/errors');

const errors = feathersErrors;

module.exports = function (...providers) {
  return context => {
    const hookProvider = (context.params || {}).provider;

    const anyProvider = providers.length === 0;
    const thisProvider = providers.some(provider =>
      provider === hookProvider ||
      (provider === 'server' && !hookProvider) ||
      (provider === 'external' && !!hookProvider)
    );

    if (anyProvider || thisProvider) {
      throw new errors.MethodNotAllowed(
        `Provider '${context.params.provider}' can not call '${context.method}'. (disallow)`
      );
    }
  };
};

Fix feathersErrors.errors === undefined error


var _each = require("lodash-node/modern/collections/forEach");

var StoreWatchMixin = function() {
  var storeNames = Array.prototype.slice.call(arguments);
  return {
    componentWillMount: function() {
      var flux = this.props.flux || this.context.flux;
      _each(storeNames, function(store) {
        flux.store(store).on("change", this._setStateFromFlux);
      }, this);
    },

    componentWillUnmount: function() {
      var flux = this.props.flux || this.context.flux;
      _each(storeNames, function(store) {
        flux.store(store).removeListener("change", this._setStateFromFlux);
      }, this);
    },

    _setStateFromFlux: function() {
      if(this.isMounted()) {
        this.setState(this.getStateFromFlux());
      }
    },

    getInitialState: function() {
      return this.getStateFromFlux();
    }
  };
};

StoreWatchMixin.componentWillMount = function() {
  throw new Error("Fluxxor.StoreWatchMixin is a function that takes one or more " +
    "store names as parameters and returns the mixin, e.g.: " +
    "mixins[Fluxxor.StoreWatchMixin(\"Store1\", \"Store2\")]");
};

module.exports = StoreWatchMixin;

var _each = require("lodash-node/modern/collections/forEach");

var StoreWatchMixin = function() {
  var storeNames = Array.prototype.slice.call(arguments);
  return {
    componentDidMount: function() {
      var flux = this.props.flux || this.context.flux;
      _each(storeNames, function(store) {
        flux.store(store).on("change", this._setStateFromFlux);
      }, this);
    },

    componentWillUnmount: function() {
      var flux = this.props.flux || this.context.flux;
      _each(storeNames, function(store) {
        flux.store(store).removeListener("change", this._setStateFromFlux);
      }, this);
    },

    _setStateFromFlux: function() {
      if(this.isMounted()) {
        this.setState(this.getStateFromFlux());
      }
    },

    getInitialState: function() {
      return this.getStateFromFlux();
    }
  };
};

StoreWatchMixin.componentWillMount = function() {
  throw new Error("Fluxxor.StoreWatchMixin is a function that takes one or more " +
    "store names as parameters and returns the mixin, e.g.: " +
    "mixins[Fluxxor.StoreWatchMixin(\"Store1\", \"Store2\")]");
};

module.exports = StoreWatchMixin;

Change StoreWatchMixin to watch in componentDidMount


var inherits = require('util').inherits,
    Task = require('./Task'),
    gulp = require('gulp'),
    _ = require('lodash');

var ListingTask = function (buildHelper) {
    Task.call(this, buildHelper);
};

inherits(ListingTask, Task);

ListingTask.prototype.command = "tasks";
ListingTask.prototype.availableToModule = false;
ListingTask.prototype.action = function () {
    console.log();
    _.forEach(gulp.tree(), _.ary(console.log, 1));
    console.log();
};

module.exports = ListingTask;

var inherits = require('util').inherits,
    Task = require('./Task'),
    gulp = require('gulp'),
    _ = require('lodash');

var ListingTask = function (buildHelper) {
    Task.call(this, buildHelper);
};

inherits(ListingTask, Task);

ListingTask.prototype.command = "tasks";
ListingTask.prototype.action = function () {
    console.log();
    _.forEach(gulp.tree(), _.ary(console.log, 1));
    console.log();
};

module.exports = ListingTask;

Enable listing task to modules


Package.describe({
	name:"lepozepo:cloudinary",
	summary: "Upload files to Cloudinary",
	version:"4.2.0",
	git:"https://github.com/Lepozepo/cloudinary"
});

Npm.depends({
	cloudinary: "1.3.1",
	"cloudinary-jquery": "2.0.9"
});

Package.on_use(function (api){
	api.versionsFrom('METEOR@1.0');

	// Core Packages
	api.use(["meteor-base@1.0.1","coffeescript","mongo"], ["client", "server"]);
	api.use(["templating"], "client");
	api.imply(["check","random","reactive-var"], ["client","server"]);

	// External Packages
	api.use(["matb33:collection-hooks@0.7.3"], ["client", "server"],{weak:true});

	// Cloudinary Client Side
	api.add_files(".npm/package/node_modules/cloudinary-jquery/cloudinary-jquery.min.js","client");

	// Core Files
	api.add_files("server/configuration.coffee", "server");
	api.add_files("server/signature.coffee", "server");

	api.add_files("client/functions.coffee", "client");

	api.export && api.export("Cloudinary",["server","client"]);
	api.export && api.export("lilcloudinary", ["client"]);

});

Package.describe({
	name:"lepozepo:cloudinary",
	summary: "Upload files to Cloudinary",
	version:"4.2.0",
	git:"https://github.com/Lepozepo/cloudinary"
});

Npm.depends({
	cloudinary: "1.3.1",
	"cloudinary-jquery": "2.0.9"
});

Package.on_use(function (api){
	api.versionsFrom('METEOR@1.0');

	// Core Packages
	api.use(["meteor-base@1.0.1","coffeescript","mongo","underscore"], ["client", "server"]);
	api.use(["templating"], "client");
	api.imply(["check","random","reactive-var"], ["client","server"]);

	// External Packages
	api.use(["matb33:collection-hooks@0.7.3"], ["client", "server"],{weak:true});

	// Cloudinary Client Side
	api.add_files(".npm/package/node_modules/cloudinary-jquery/cloudinary-jquery.min.js","client");

	// Core Files
	api.add_files("server/configuration.coffee", "server");
	api.add_files("server/signature.coffee", "server");

	api.add_files("client/functions.coffee", "client");

	api.export && api.export("Cloudinary",["server","client"]);
	api.export && api.export("lilcloudinary", ["client"]);

});

Make sure we require meteor/underscore as well


// package metadata file for Meteor.js

/* jshint strict:false */
/* global Package:true */

Package.describe({
  name: 'twbs:bootstrap',  // http://atmospherejs.com/twbs/bootstrap
  summary: 'The most popular front-end framework for developing responsive, mobile first projects on the web.',
  version: '3.3.5',
  git: 'https://github.com/twbs/bootstrap.git'
});

Package.onUse(function (api) {
  api.versionsFrom('METEOR@1.0');
  api.use('jquery', 'client');
  api.addFiles([
    'dist/fonts/glyphicons-halflings-regular.eot',
    'dist/fonts/glyphicons-halflings-regular.svg',
    'dist/fonts/glyphicons-halflings-regular.ttf',
    'dist/fonts/glyphicons-halflings-regular.woff',
    'dist/fonts/glyphicons-halflings-regular.woff2',
    'dist/css/bootstrap.css',
    'dist/js/bootstrap.js'
  ], 'client');
});

// package metadata file for Meteor.js

/* jshint strict:false */
/* global Package:true */

Package.describe({
  name: 'twbs:bootstrap',  // http://atmospherejs.com/twbs/bootstrap
  summary: 'The most popular front-end framework for developing responsive, mobile first projects on the web.',
  version: '3.3.5',
  git: 'https://github.com/twbs/bootstrap.git'
});

Package.onUse(function (api) {
  api.versionsFrom('METEOR@1.0');
  api.use('jquery', 'client');
  api.addFiles([
    'dist/fonts/glyphicons-halflings-regular.eot',
    'dist/fonts/glyphicons-halflings-regular.svg',
    'dist/fonts/glyphicons-halflings-regular.ttf',
    'dist/fonts/glyphicons-halflings-regular.woff',
    'dist/fonts/glyphicons-halflings-regular.woff2'
  ], 'client', { isAsset: true });
  api.addFiles([
    'dist/css/bootstrap.css',
    'dist/js/bootstrap.js'
  ], 'client');
});

Add support for Meteor 1.2


'use strict';
angular.module('arethusa.core').directive('keyCapture', [
  'keyCapture',
  function (keyCapture) {
    return {
      restrict: 'A',
      link: function (scope, element, attrs) {
        element.on('keydown', function (event) {
          keyCapture.keydown(event);
        });
        element.on('keyup', function (event) {
          keyCapture.keyup(event);
        });
      }
    };
  }
]);

'use strict';

/**
 * @ngdoc directive
 * @name keyCapture
 * @restrict A
 *
 * @description
 * Captures keydown and keyup events on the element and
 * delegates the event handling to the keyCapture service.
 *
 * @example
   <example module="arethusa.core">
     <file name="service.js">
        angular.module('arethusa.core').service('keyCapture', function() {
          this.keydown = function(event) {
            console.log(event);
          };
        });
     </file>
     <file name="index.html">
      <div keyCapture>
        Some awesome stuff
      </div>
     </file>
   </example>
 */
angular.module('arethusa.core').directive('keyCapture', [
  'keyCapture',
  function (keyCapture) {
    return {
      restrict: 'A',
      link: function (scope, element, attrs) {
        element.on('keydown', function (event) {
          keyCapture.keydown(event);
        });
        element.on('keyup', function (event) {
          keyCapture.keyup(event);
        });
      }
    };
  }
]);

Add example documentation (not yet working)


const searchEntitySelector = '.js-search-entity'

const SearchAnalytics = {
  init() {
    this.pageNumber =
      new URLSearchParams(window.location.search).get('page') || 1
    const entities = document.querySelectorAll(searchEntitySelector)
    if (entities) {
      for (let i = 0; i < entities.length; i++) {
        entities[i].addEventListener('click', this.onClickHandler.bind(this))
      }
    }
  },

  pushAnalyticsEvent({
    searchResultRank,
    searchResultPageNumber,
    searchCategory,
  }) {
    window.dataLayer = window.dataLayer || []
    window.dataLayer.push({
      event: 'searchResultClick',
      searchResultPageNumber,
      searchResultRank,
      searchCategory,
    })
  },

  onClickHandler(e) {
    const target = e.target
    if (target) {
      this.pushAnalyticsEvent({
        searchResultRank: target.dataset.searchResultRank,
        searchResultPageNumber: this.pageNumber,
        searchCategory: target.dataset.searchCategory,
      })
    }
  },
}

module.exports = SearchAnalytics

const searchEntitySelector = '.js-search-entity'

const SearchAnalytics = {
  init() {
    this.pageNumber =
      new URLSearchParams(window.location.search).get('page') || 1
    const entities = document.querySelectorAll(searchEntitySelector)
    if (entities) {
      for (let i = 0; i < entities.length; i++) {
        entities[i].addEventListener('click', this.onClickHandler.bind(this))
      }
    }
  },

  pushAnalyticsEvent({
    searchResultRank,
    searchResultPageNumber,
    searchCategory,
  }) {
    window.dataLayer = window.dataLayer || []
    window.dataLayer.push({
      event: 'searchResultClick',
      searchResultPageNumber,
      searchResultRank,
      searchCategory,
    })
  },

  onClickHandler(e) {
    const target = e.currentTarget
    if (target) {
      this.pushAnalyticsEvent({
        searchResultRank: target.dataset.searchResultRank,
        searchResultPageNumber: this.pageNumber,
        searchCategory: target.dataset.searchCategory,
      })
    }
  },
}

module.exports = SearchAnalytics

Correct search onclick event delegation by using currentTarget


angular.module('private.logout', [
])
.config(function ($stateProvider) {
    $stateProvider
        .state('wegas.private.logout', {
            url: 'logout',
        	views: {
    		 	'workspace': {
                    controller: 'LogoutController as logoutCtrl',
                }
            }
        })
    ;
})
.controller('LogoutController', function LogoutController($state, Auth, SessionsModel, ScenariosModel, Flash) {
    console.log("Logout!");
    Auth.logout().then(function(response){
    	SessionsModel.clearCache();
    	ScenariosModel.clearCache();
    	Flash(response.level, response.message);
        $state.go("wegas.public.login");
    });

});

angular.module('private.logout', [
])
.config(function ($stateProvider) {
    $stateProvider
        .state('wegas.private.logout', {
            url: 'logout',
        	views: {
    		 	'workspace': {
                    controller: 'LogoutController as logoutCtrl',
                }
            }
        })
    ;
})
.controller('LogoutController', function LogoutController($state, Auth, SessionsModel, ScenariosModel, Flash) {
    console.log("Logout!");
    Auth.logout().then(function(response){
    	SessionsModel.clearCache();
    	ScenariosModel.clearCache();
    	response.flash();
        $state.go("wegas.public.login");
    });

});

Edit flash message for logout


import React from 'react';

import List from 'src/List';
import ListRow from 'src/ListRow';

import Button from 'src/Button';
import TextLabel from 'src/TextLabel';

import DebugBox from '../DebugBox';

function NormalList() {
    return (
        <DebugBox width="30rem">
            <List variant="normal" title="List title" desc="Help text here">
                <ListRow>
                    <TextLabel icon="tickets" basic="Hello World" />
                </ListRow>
                <ListRow highlight>
                    <TextLabel icon="tickets" basic="Highlighted row" />
                </ListRow>
                <ListRow>
                    <TextLabel icon="tickets" basic="Row 3" />
                </ListRow>
                <ListRow>
                    <Button
                        icon="add"
                        basic="Add row" />
                </ListRow>
            </List>
        </DebugBox>
    );
}

export default NormalList;

import React from 'react';

import List from 'src/List';
import ListRow from 'src/ListRow';

import Button from 'src/Button';
import TextLabel from 'src/TextLabel';

import DebugBox from '../DebugBox';

function NormalList() {
    return (
        <DebugBox width="30rem">
            <List variant="normal" title="List title" desc="Help text here">
                <ListRow>
                    <TextLabel icon="tickets" basic="Hello World" />
                </ListRow>

                <ListRow
                    desc="Row help message"
                    status="error"
                    errorMsg="Row error message">
                    <TextLabel
                        icon="tickets"
                        basic="Hello World"
                        aside="Component aside" />
                </ListRow>

                <ListRow highlight>
                    <TextLabel icon="tickets" basic="Highlighted row" />
                </ListRow>
                <ListRow>
                    <TextLabel icon="tickets" basic="Row 3" />
                </ListRow>
                <ListRow>
                    <Button
                        icon="add"
                        basic="Add row" />
                </ListRow>
            </List>
        </DebugBox>
    );
}

export default NormalList;

Update example for revised <ListRow>


(function(app) {
  'use strict';

  var dom = app.dom || require('../dom.js');
  var Button = app.Button || require('./button.js');

  var LoadButton = Button.inherits(function(props) {
    this.loader = props.loader;

    this.registerChangeListener();
  });

  LoadButton.prototype.inputElement = function() {
    return dom.child(this.element(), 2);
  };

  LoadButton.prototype.registerChangeListener = function() {
    dom.on(this.inputElement(), 'change', LoadButton.prototype.onchange.bind(this));
  };

  LoadButton.prototype.ontap = function() {
    dom.click(this.inputElement());
  };

  LoadButton.prototype.onchange = function(event) {
    var file = dom.file(dom.target(event));
    if (file) {
      this.loader(file);
    }
  };

  if (typeof module !== 'undefined' && module.exports) {
    module.exports = LoadButton;
  } else {
    app.LoadButton = LoadButton;
  }
})(this.app || (this.app = {}));

(function(app) {
  'use strict';

  var dom = app.dom || require('../dom.js');
  var Button = app.Button || require('./button.js');

  var LoadButton = Button.inherits(function(props) {
    this.loader = props.loader;

    this.registerChangeListener();
  });

  LoadButton.prototype.inputElement = function() {
    return dom.child(this.element(), 2);
  };

  LoadButton.prototype.registerChangeListener = function() {
    dom.on(this.inputElement(), 'change', LoadButton.prototype.onchange.bind(this));
  };

  LoadButton.prototype.ontap = function() {
    dom.click(this.inputElement());
  };

  LoadButton.prototype.onchange = function(event) {
    this.loader(dom.file(dom.target(event)));
  };

  if (typeof module !== 'undefined' && module.exports) {
    module.exports = LoadButton;
  } else {
    app.LoadButton = LoadButton;
  }
})(this.app || (this.app = {}));

Remove unnecessary check for loading file


import React from 'react';

import { Strings } from '../../constants';

export default React.createClass({

  propTypes: {
    field       : React.PropTypes.string,
    onClick     : React.PropTypes.func,
    valueOn     : React.PropTypes.string,
    valueOff    : React.PropTypes.string,
    checked     : React.PropTypes.bool,
  },

  getDefaultProps () {
    return {
      valueOn   : "Ativo",
      valueOff  : "Desativado",
      checked   : false,
      onChange: function (event) { void event; },
    }
  },

  getInitialState () {
    return {
      valueOn: this.props.valueOn,
      valueOff: this.props.valueOff,
      value: this.props.checked,
    }
  },

  getText () {
    return this.refs[this.props.field].state.placeholder;
  },

  getValue () {
    const value = this.refs[this.props.field].state.checked;

    return value;
  },

  onChange (event) {
    this.setState({ value: event.target.checked });
    this.props.onChange(event);
  },

  render () {

    return (

          {this.props.valueOff}
          <input ref={this.props.field} checked={this.state.value} name={this.props.field} type="checkbox" onChange={this.onChange}/>

          {this.props.valueOn}

    );
  }

});

import React from 'react';

import { Strings } from '../../constants';

export default React.createClass({

  propTypes: {
    field       : React.PropTypes.string,
    onClick     : React.PropTypes.func,
    valueOn     : React.PropTypes.string,
    valueOff    : React.PropTypes.string,
    checked     : React.PropTypes.bool,
    onChange: React.PropTypes.func,
  },

  getDefaultProps () {
    return {
      valueOn   : "Ativo",
      valueOff  : "Desativado",
      checked   : false,
    }
  },

  getInitialState () {
    return {
      valueOn: this.props.valueOn,
      valueOff: this.props.valueOff,
      value: this.props.checked,
    }
  },

  getText () {
    return this.refs[this.props.field].state.placeholder;
  },

  getValue () {
    const value = this.refs[this.props.field].state.checked;

    return value;
  },

  onChange (event) {
    this.setState({ value: event.target.checked });

    if (this.props.onChange) {
      this.props.onChange(event.target.checked);
    }
  },

  render () {

    return (

          {this.props.valueOff}
          <input ref={this.props.field} checked={this.state.value} name={this.props.field} type="checkbox" onChange={this.onChange}/>

          {this.props.valueOn}

    );
  }

});

Fix onChange propType in Switch component


var _ = require('lodash');
var datafiles = require('./datafiles');

module.exports = {
  dataFileVariables: function (config, path) {
    let dataVars = {};
    let scopes = _.filter(config.data_file_variables, function (v) {
      return (_.isEmpty(v.scope.path) || new RegExp(v.scope.path).test(path));
    });

    _.forEach(scopes, function (scope) {
      dataVars = _.merge(dataVars, scope.values);
    });

    return dataVars;
  },

  setupConfig: function (source, metadata) {
    let pageVars = _.isEmpty(source) ? {} : this.dataFileVariables(metadata.config, source)
    let config = {
      page: pageVars
    };

    return _.merge({
      'data': datafiles.data,
      'config': metadata.config
    }, config);
  }

};

var _ = require('lodash');
var datafiles = require('./datafiles');

module.exports = {
  dataFileVariables: function (config, path) {
    // There is no config.yml
    if (_.isUndefined(config)) {
      return {};
    }

    let dataVars = {};
    let scopes = _.filter(config.data_file_variables, function (v) {
      return (_.isEmpty(v.scope.path) || new RegExp(v.scope.path).test(path));
    });

    _.forEach(scopes, function (scope) {
      dataVars = _.merge(dataVars, scope.values);
    });

    return dataVars;
  },

  setupConfig: function (source, metadata) {
    let pageVars = _.isEmpty(source) ? {} : this.dataFileVariables(metadata.config, source)
    let config = {
      page: pageVars
    };

    return _.merge({
      'data': datafiles.data,
      'config': metadata.config
    }, config);
  }

};

Fix crash in data reading


var express = require('express');
var path = require('path');
var FlightAware = require('flightaware.js');

// Get access to the FlightAware 2.0 client API ...
// See http://flightaware.com/commercial/flightxml for username/apiKey ...
var username = 'your-flightaware-username';
var apiKey = 'your-flightaware-apiKey';
var client = new FlightAware(username, apiKey);

var app = express();
app.get('/', function(req, res) {
  res.sendFile(path.join(__dirname, 'index.html'));
});

app.get('/api/Arrived/:airport', function(req, res) {
    client.Arrived({
        airport: req.params.airport,
    }, function(err, result) {
        if (err) return res.send(err);
        res.json(result);
    });
});

var port = 8000;
app.listen(port, function() {
  console.log("Node app is running at http://localhost:" + port);
});

var express = require('express');
var path = require('path');
var FlightAware = require('flightaware.js');
var config = require('./config');

// Get access to the FlightAware 2.0 client API ...
// See http://flightaware.com/commercial/flightxml for username/apiKey ...
var client = new FlightAware(config.username, config.apiKey);

var app = express();
app.get('/', function(req, res) {
  res.sendFile(path.join(__dirname, 'index.html'));
});

app.get('/api/Arrived/:airport', function(req, res) {
    client.Arrived({
        airport: req.params.airport,
    }, function(err, result) {
        if (err) return res.send(err);
        res.json(result);
    });
});

var port = 8000;
app.listen(port, function() {
  console.log("Node app is running at http://localhost:" + port);
});

Use a config file for the FlightAware keys.


var express = require('express');

var app = express();

var port = process.env.PORT || 8080

app.get('/', function (req, res) {

  res.send('Hello World!');
});

app.listen(port, function () {
  console.log('Example app listening on port '+ port +'!');
});

var express = require('express');
var strftime = require('strftime');
var app = express();
console.log(strftime('%B %d, %Y %H:%M:%S')); // => April 28, 2011 18:21:08
console.log(strftime('%F %T', new Date(1307472705067))); // => 2011-06-07 18:51:45

var port = process.env.PORT || 8080;

app.get('/', function (req, res) {

  res.send('Output goes here!');
});

app.listen(port, function () {
  console.log('Example app listening on port '+ port +'!');
});

Add strftime library for date formatting


/* global Node */

import _default from "ember-views/views/states/default";
import { create } from "ember-metal/platform";
import merge from "ember-metal/merge";
import jQuery from "ember-views/system/jquery";

/**
@module ember
@submodule ember-views
*/
var preRender = create(_default);

var containsElement;
if (typeof Node === 'object') {
  containsElement = Node.prototype.contains;

  if (!containsElement && Node.prototype.compareDocumentPosition) {
    // polyfill for older Firefox.
    // http://compatibility.shwups-cms.ch/en/polyfills/?&id=52
    containsElement = function(node){
      return !!(this.compareDocumentPosition(node) & 16);
    };
  }
} else {
  containsElement = function(element) {
    return this.contains(element);
  };
}

export default preRender;

import _default from "ember-views/views/states/default";
import { create } from "ember-metal/platform";
import merge from "ember-metal/merge";
import jQuery from "ember-views/system/jquery";

/**
@module ember
@submodule ember-views
*/
var preRender = create(_default);

export default preRender;

Remove dead code and polyfill for containsElement.


var express = require('express');
var xml = require('xml');
var app = express();
var suncalc = require('suncalc');
var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/sunrisedb');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error...'));
db.once('open', function callback() {
    console.log('multivision db opened');
});

app.get('/xml', function(req, res) {
    var xmlresult = {
    APe: "35", Mandis: "32"
    };
    res.set('Content-Type', 'text/xml');
    res.send(xml(xmlresult));
});

app.get('*', function(req, res) {
    // get today's sunlight times for London
    var times = suncalc.getTimes(new Date(), 59.313, 18.065);
    res.json(times);
});

var port = 3000;
app.listen(port);
console.log('Listen on port: ' + port + '...');

var express = require('express');
var xml = require('xml');
var app = express();
var suncalc = require('suncalc');
var mongoose = require('mongoose');

mongoose.connect('mongodb://localhost/sunrisedb');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error...'));
db.once('open', function callback() {
    console.log('multivision db opened');
});

app.get('/xml', function(req, res) {
    var xmlresult = {
    APe: "35", Mandis: "32"
    };
    res.set('Content-Type', 'text/xml');
    res.send(xml(xmlresult));
});

app.get('*', function(req, res) {
    var lat = req.query.lat;
    var lon = req.query.lon;
    var date = new Date(req.query.date);
    var times = suncalc.getTimes(date, lat, lon);
    res.json(times);
});

var port = 3000;
app.listen(port);
console.log('Listen on port: ' + port + '...');

Read query prarms for lat, long and date.


export default function createEagerSchema({embedCode, properties}) {
  embedCode = JSON.stringify(embedCode)

  const initializeApp = function initializeApp(embedCodeInjection) {
    if (!window.addEventListener) return // Check for IE9+

    const TRACKED_ENTITY_PATTERN = /TRACKED_ENTITY\[(\S+)\]/g
    const options = INSTALL_OPTIONS

    const insertOption = (match, key) => options[key]

    function insertEmbedCode() {
      document.head.innerHTML += embedCodeInjection.replace(TRACKED_ENTITY_PATTERN, insertOption)

      eval(document.head.lastChild.textContent) // eslint-disable-line no-eval
    }

    if (document.readyState === "loading") {
      document.addEventListener("DOMContentLoaded", insertEmbedCode)
    }
    else {
      insertEmbedCode()
    }
  }.toString()

  const installJSON = {
    resources: {
      body: [
        {
          type: "script",
          contents: `(${initializeApp}(${embedCode}))`
        }
      ]
    },

    options: {properties}
  }

  return installJSON
}

export default function createEagerSchema({embedCode, properties}) {
  embedCode = JSON.stringify(embedCode)

  const initializeApp = function initializeApp(embedCodeInjection) {
    if (!window.addEventListener) return // Check for IE9+

    const TRACKED_ENTITY_PATTERN = /TRACKED_ENTITY\[(\S+)\]/g
    const options = INSTALL_OPTIONS

    const insertOption = (match, key) => options[key]

    function insertEmbedCode() {
      const serializer = document.createElement("div")

      serializer.innerHTML = embedCodeInjection.replace(TRACKED_ENTITY_PATTERN, insertOption)

      Array.prototype.forEach.call(serializer.children, element => {
        document.body.appendChild(element)

        if (element.nodeName === "SCRIPT") {
          eval(element.textContent) // eslint-disable-line no-eval
        }
      })
    }

    if (document.readyState === "loading") {
      document.addEventListener("DOMContentLoaded", insertEmbedCode)
    }
    else {
      insertEmbedCode()
    }
  }.toString()

  const installJSON = {
    resources: {
      body: [
        {
          type: "script",
          contents: `(${initializeApp}(${embedCode}))`
        }
      ]
    },

    options: {properties}
  }

  return installJSON
}

Support multiple tags in embed code.


// code.google.com/speed/webp/
// by rich bradshaw, ryan seddon, and paul irish

// This test is ascynchronous. Watch out.

(function(){

  var image = new Image();

  image.onerror = function() {
      Modernizr.addTest('webp', function () { return false; });
  };
  image.onload = function() {
      Modernizr.addTest('webp', function () { return image.width == 4; });
  };

  image.src = 'data:image/webp;base64,UklGRjgAAABXRUJQVlA4ICwAAAAQAgCdASoEAAQAAAcIhYWIhYSIgIIADA1gAAUAAAEAAAEAAP7%2F2fIAAAAA';

})();

// code.google.com/speed/webp/
// by rich bradshaw, ryan seddon, and paul irish

// This test is ascynchronous. Watch out.

(function(){

  var image = new Image();

  image.onerror = function() {
      Modernizr.addTest('webp', false);
  };
  image.onload = function() {
      Modernizr.addTest('webp', function() { return image.width == 4; });
  };

  image.src = 'data:image/webp;base64,UklGRjgAAABXRUJQVlA4ICwAAAAQAgCdASoEAAQAAAcIhYWIhYSIgIIADA1gAAUAAAEAAAEAAP7%2F2fIAAAAA';

}());

Use just `false` instead of `function() { return false; }` if the test already failed.