// Define search and replace terms for image src link
let search = /s[0-9]+/g;
let replace = 's512';

function getProfileImageContainer() {
    // Get profile image containers
    return $('#channel-header-container');
}

function getProfileImage(container) {
    // Get profile image tag
    return container.find('img');
}

function wrapEnlargeLink() {
    // Get profile image link
    let imageContainer = getProfileImageContainer();

    // No image?
    if (!imageContainer.length) {
        return;
    }

    // Get img tag nested within container
    let imageTag = getProfileImage(imageContainer);

    // No tag?
    if (!imageTag.length) {
        return;
    }

    // Get image src URL
    let src = imageTag.attr('src');

    // Replace image pixel value in URL for a larger 512px image
    src = src.replace(search, replace);

    // Wrap image tag with a link that points to the larger image
    $( imageTag ).wrap( "" );
}

// One-time injection
wrapEnlargeLink();

// Define search and replace terms for image src link
let search = /\/s[0-9]+/g;
let replace = 's512';

function getProfileImageContainer() {
    // Get profile image containers
    return $('#channel-header-container');
}

function getProfileImage(container) {
    // Get profile image tag
    return container.find('img');
}

function wrapEnlargeLink() {
    // Get profile image link
    let imageContainer = getProfileImageContainer();

    // No image?
    if (!imageContainer.length) {
        return;
    }

    // Get img tag nested within container
    let imageTag = getProfileImage(imageContainer);

    // No tag?
    if (!imageTag.length) {
        return;
    }

    // Get image src URL
    let src = imageTag.attr('src');

    // Replace image pixel value in URL for a larger 512px image
    src = src.replace(search, replace);

    // Wrap image tag with a link that points to the larger image
    $( imageTag ).wrap( "" );
}

// One-time injection
wrapEnlargeLink();

Improve image size replacement regex


var createEditor;
var author;

function injectCreate(id) {
    $("#" + id).load("create/html/createHTML", function() {
        injectCreateEditor();

	// Generate a random number from 1 to 10000
        author = Math.floor((Math.random() * 10000) + 1);
    });
}

function injectCreateEditor() {
    Range = ace.require('ace/range').Range;

    createEditor = ace.edit("editor");
    createEditor.setTheme("ace/theme/github");

    // Set this to RESOLVE mode
    var ResolveMode = ace.require("ace/mode/resolve").Mode;
    createEditor.session.setMode(new ResolveMode());

    // Gets rid of a weird Ace Editor bug
    //createEditor.$blockScrolling = Infinity;

    createEditor.getSession().on('change', removeAllVCMarkers);
    createEditor.setFontSize(18);
}

var createEditor;
var author;

function injectCreate(id) {
    $("#" + id).load("create/html/createHTML", function() {
        injectCreateEditor();

	// Generate a random number from 1 to 10000
        author = Math.floor((Math.random() * 10000) + 1);
    });
}

function injectCreateEditor() {
    Range = ace.require('ace/range').Range;

    createEditor = ace.edit("editor");
    createEditor.setTheme("ace/theme/github");

    // Set this to RESOLVE mode
    //var ResolveMode = ace.require("ace/mode/resolve").Mode;
    //createEditor.session.setMode(new ResolveMode());

    // Gets rid of a weird Ace Editor bug
    //createEditor.$blockScrolling = Infinity;

    createEditor.getSession().on('change', removeAllVCMarkers);
    createEditor.setFontSize(18);
}

Resolve mode does not support some of the syntax


/**
 * Creo le variabili globali necessarie per il corretto funzionamento di
 * Chronos.
 *
 * Created by amantova on 21/02/16.
 */

// Ogni plugin dovra' specificare in questa variabile il suo nome, in tal
// maniera si potra' eseguire la procedura d'esecuzione dei moduli senza
// specificare il nome del plugin, accorciando la stringa del paramentro.
// E' compito del modulo di trasmissione al plugin manager process come viene
// definito la forma abbreviata da usare.
var __plugin = undefined;

const __SCOPING_OPERATOR = '::';

/**
 * Creo le variabili globali necessarie per il corretto funzionamento di
 * Chronos.
 *
 * Created by amantova on 21/02/16.
 */

// Ogni plugin dovra' specificare in questa variabile il suo nome, in tal
// maniera si potra' eseguire la procedura d'esecuzione dei moduli senza
// specificare il nome del plugin, accorciando la stringa del paramentro.
// E' compito del modulo di trasmissione al plugin manager process come viene
// definito la forma abbreviata da usare.
var __plugin = undefined;

const __GIT_PATH = "https://github.com/";

const __SCOPING_OPERATOR = '::';

Add git path defualt value


/* jshint node: true */

module.exports = function(grunt) {
  "use strict";

  grunt.initConfig({
      pkg: grunt.file.readJSON('package.json')
    , jshint: {
        all: [
            "Gruntfile.js"
          , "lib/*.js"
          , "spec/**/*.js"
        ]
      , options: {
          jshintrc: '.jshintrc'
        },
      }
    , jasmine: {
        src: "lib/*.js"
      , options: {
          specs: "spec/**/*.js"
        , vendor: "vendor/**/*.js"
      }
    }
  })

  grunt.loadNpmTasks('grunt-contrib-jshint')
  grunt.loadNpmTasks('grunt-contrib-jasmine')

  grunt.registerTask('test', ['jshint', 'jasmine'])
  grunt.registerTask('default', ['test'])
};

/* jshint node: true */

module.exports = function(grunt) {
  "use strict";

  grunt.initConfig({
      pkg: grunt.file.readJSON('package.json')
    , jshint: {
        all: [
            "Gruntfile.js"
          , "lib/**/*.js"
          , "spec/**/*.js"
        ]
      , options: {
          jshintrc: '.jshintrc'
        },
      }
    , jasmine: {
        src: "lib/*.js"
      , options: {
          specs: "spec/**/*.js"
        , vendor: "vendor/**/*.js"
      }
    }
  })

  grunt.loadNpmTasks('grunt-contrib-jshint')
  grunt.loadNpmTasks('grunt-contrib-jasmine')

  grunt.registerTask('test', ['jshint', 'jasmine'])
  grunt.registerTask('default', ['test'])
};

Use glob to find lib


var should = require('should');
var webdriverio = require('webdriverio');
var selenium = require('selenium-standalone');
var fs = require('fs');
var path = require('path');

var client = webdriverio.remote({
  logLevel: 'command',
  desiredCapabilities: {
    browserName: 'phantomjs'
  }
});

describe.only('Clientside validation', function() {

  this.timeout(30000);

  before(function(done){
    selenium.install(
      {
        logger: function (message) {
          console.log(message);
        }
      },
      function (err) {
        if (err) return done(err);

        selenium.start(function() {
          done();
        });
      }
    );

  });

  it('should display a summary of errors when submitting an incomplete form', function(done) {

    client
      .init()
      .url('http://localhost:3000/components/elements/land-registry/clientside-form-validation/demo/')
      .setValue('#full-name', 'WebdriverIO')
      .click('#submit')
      .element('.error-summary')
      .call(done);

      // .screenshot()
      // .then(function(data) {
      //   var binaryData = new Buffer(data.value, 'base64').toString('binary');
      //   fs.writeFileSync(path.join(process.cwd(), '/.tmp/screenshot.png'), binaryData, 'binary');
      // })

  });

  after(function(done) {
    done();
  });

});

var should = require('should');
var webdriverio = require('webdriverio');
var selenium = require('selenium-standalone');
var fs = require('fs');
var path = require('path');

var client = webdriverio.remote({
  logLevel: 'command',
  desiredCapabilities: {
    browserName: 'phantomjs'
  }
});

describe('Clientside validation', function() {

  this.timeout(30000);

  before(function(done){
    selenium.install(
      {
        logger: function (message) {
          console.log(message);
        }
      },
      function (err) {
        if (err) return done(err);

        selenium.start(function() {
          done();
        });
      }
    );

  });

  it('should display a summary of errors when submitting an incomplete form', function(done) {

    client
      .init()
      .url('http://localhost:3000/components/elements/land-registry/clientside-form-validation/demo/')
      .setValue('#full-name', 'WebdriverIO')
      .click('#submit')
      .element('.error-summary')
      .call(done);

      // .screenshot()
      // .then(function(data) {
      //   var binaryData = new Buffer(data.value, 'base64').toString('binary');
      //   fs.writeFileSync(path.join(process.cwd(), '/.tmp/screenshot.png'), binaryData, 'binary');
      // })

  });

  after(function(done) {
    done();
  });

});

Undo accidental restriction of test suite


/*global contract, config, it, assert, before*/
const Resolver = require('Embark/contracts/Resolver');

const namehash = require('eth-ens-namehash');
const address = '0x38ac14a9B6a7c8F9C46e4804074186c9F201D0A0';
const rootNode = namehash.hash('embark.eth');

config({
  contracts: {
    "ENSRegistry": {
      "args": []
    },
    "Resolver": {
      "args": ["$ENSRegistry"]
    },
    "FIFSRegistrar": {
      "args": ["$ENSRegistry", rootNode],
      "onDeploy": [
        `ENSRegistry.methods.setOwner('${rootNode}', web3.eth.defaultAccount).send().then(() => {
          ENSRegistry.methods.setResolver('${rootNode}', "$Resolver").send();
          Resolver.methods.setAddr('${rootNode}', '${address}').send().then(() => {
            global.ensTestReady = true;
          });
        });`
      ]
    }
  }
});

contract("ENS", function () {
  this.timeout(1000);

  before(function (done) {
  //   Wait for onDeploy to finish
    const wait = setInterval(() => {
      if (!global.ensTestReady) {
        return;
      }
      clearInterval(wait);
      done();
    }, 50);
  });

  it("should have registered embark.eth", async function () {
    const domainAddress = await Resolver.methods.addr(rootNode).call();
    assert.strictEqual(domainAddress, address);
  });
});

/*global contract, config, it, assert, before*/
const Resolver = require('Embark/contracts/Resolver');

const namehash = require('eth-ens-namehash');
const address = '0x38ac14a9B6a7c8F9C46e4804074186c9F201D0A0';
const rootNode = namehash.hash('embark.eth');

config({
  contracts: {
    "ENSRegistry": {
      "args": []
    },
    "Resolver": {
      "args": ["$ENSRegistry"]
    },
    "FIFSRegistrar": {
      "args": ["$ENSRegistry", rootNode],
      "onDeploy": [
        `ENSRegistry.methods.setOwner('${rootNode}', web3.eth.defaultAccount).send().then(() => {
          ENSRegistry.methods.setResolver('${rootNode}', "$Resolver").send();
          Resolver.methods.setAddr('${rootNode}', '${address}').send();
        });`
      ]
    }
  }
});

contract("ENS", function () {
  it("should have registered embark.eth", function () {
    let maxRetry = 20;
    let domainAddress;

    const wait = setInterval(async () => {
      domainAddress = await Resolver.methods.addr(rootNode).call();
      if (domainAddress || maxRetry === 0) {
        clearInterval(wait);
        assert.strictEqual(domainAddress, address);
        return;
      }
      maxRetry--;
    }, 50);
  });
});

Update ENS test using global


'use strict';
var cp = require('child_process');
var child = cp.fork(__dirname + '/child.js');

module.exports = {

  saveBin: function(bin, user) {
    child.send({
      bin: bin,
      user: user
    });
  }

};

'use strict';
var cp = require('child_process');
var child = cp.fork(__dirname + '/child.js');
var passport = require('passport');
var DropboxOAuth2Strategy = require('passport-dropbox-oauth2').Strategy;
var active = false;

module.exports = function (options) {
  return {
    initialize: function () {
      active = true;
      passport.use(new DropboxOAuth2Strategy({
        clientID: options.dropbox.id,
        clientSecret: options.dropbox.secret,
        callbackURL: 'http://jsbin.dev/auth/dropbox/callback'
      }, function (accessToken, refreshToken, profile, done) {
        done(null, profile);
      }
    ));
    }
  };
};

  saveBin: function(bin, user) {
    child.send({
      bin: bin,
      user: user
    });
  }

};

Move module.eexports to a function so we can setup passport for dropbox


app.factory('stocks', ['$http', function($http) {
	return {
		stocks: [],
		getAll: function() {
			var self = this;
			return $http.get('http://localhost:3000/stocks')
				.success(function(data) {
					angular.copy(data, self.stocks);
					// return data;
				})
				.error(function(data) {
					return data;
				});
		},

		get: function(symbol) {
			var self = this;
			return $http.get('http://localhost:3000/stocks/' + symbol)
				.success(function(data) {
					return data;
				});
		},

		create: function(data) {
			var self = this;
			return $http.post('http://localhost:3000/stocks', data)
				.success(function(data) {
					self.stocks.push(data);
				})
				.error(function(data) {
					return data;
				})
		}
	}

}]);

app.factory('stocks', ['$http', function ($http) {
  return {
    stocks: [],

    getAll: function () {
      var self = this;
      return $http.get('http://localhost:3000/stocks')
        .success(function (data) {
          angular.copy(data, self.stocks);
          // return data;
        })
        .error(function (data) {
          return data;
        });
    },

    get: function (symbol) {
      var self = this;
      return $http.get('http://localhost:3000/stocks/' + symbol)
        .success(function (data) {
          return data;
        });
    },

    create: function (data) {
      var self = this;
      return $http.post('http://localhost:3000/stocks', data)
        .success(function (data) {
          self.stocks.push(data);
        })
        .error(function (data) {
          return data;
        })
    }
  }

}]);

Use spaces instead of tabs


"use strict";
let db = require('./db');

function generateStub(length) {
  let result = ""
  for(let i = 0; i < length; i++) {
    let value = Math.round(Math.random() * 36)
    if (value > 9)
      result += String.fromCharCode(value + 87);
    else
      result += value
  }
  return result;
}

function shortenUrl(req, res) {
  let url = req.params.url;
  let nurl = generateStub(5);
  let collision = false;

  while(collision) {
    db.oneOrNone('select exists(select * from urls where nurl = \'a2085\' limit 1);', nurl)
    .then(function(data) {
      if (data.exists) {
        nurl = generateStub(5);
        collision = true;
      } else
        collision = false;
    }).catch(function(error) {
      console.log('Error: ' + error);
      res.send(500);
    });
  }

  db.none('insert into urls(url, nurl) values($1, $2);', [url, nurl]);
  res.jsonp({
    "oldurl" : url,
    "newurl" : req.host + '/' + nurl
  });
}

module.exports = shortenUrl;

"use strict";
let db = require('./db');

function generateStub(length) {
  let result = ""
  for(let i = 0; i < length; i++) {
    let value = Math.round(Math.random() * 36)
    if (value > 9)
      result += String.fromCharCode(value + 87);
    else
      result += value
  }
  return result;
}

function shortenUrl(req, res) {
  let url = req.params.url;
  let nurl = generateStub(5);
  let collision = false;

  while(collision) {
    db.oneOrNone('select exists(select * from urls where nurl = $1 limit 1);', nurl)
    .then(function(data) {
      if (data.exists) {
        nurl = generateStub(5);
        collision = true;
      } else
        collision = false;
    }).catch(function(error) {
      console.log('Error: ' + error);
      res.send(500);
    });
  }

  db.none('insert into urls(url, nurl) values($1, $2);', [url, nurl]);
  res.jsonp({
    "oldurl" : url,
    "newurl" : req.host + '/' + nurl
  });
}

module.exports = shortenUrl;

Remove hard coded value left by accident


var assert = require("assert");

module.exports = {
  "User set saved profile": function(browser) {
    browser
      .url(browser.launch_url)
      .waitForElementVisible(".fa-sign-in")
      .click(".fa-sign-in")
      .setValue("#email", "test@lesspass.com")
      .setValue("#passwordField", "test@lesspass.com")
      .waitForElementVisible("#encryptMasterPassword__btn")
      .click("#encryptMasterPassword__btn")
      .waitForElementVisible("#signInButton")
      .click("#signInButton")
      .waitForElementVisible(".fa-key")
      .click(".fa-key")
      .waitForElementVisible(".passwordProfile__site")
      .click(".passwordProfile__site")
      .waitForElementVisible("#site")
      .assert.value("#site", "example.org")
      .assert.value("#login", "contact@example.org");

    browser.end();
  }
};

var assert = require("assert");

module.exports = {
  "User set saved profile": function(browser) {
    browser
      .url(browser.launch_url)
      .waitForElementVisible(".fa-sign-in")
      .click(".fa-sign-in")
      .setValue("#email", "test@lesspass.com")
      .setValue("#passwordField", "test@lesspass.com")
      .waitForElementVisible("#encryptMasterPassword__btn")
      .click("#encryptMasterPassword__btn")
      .waitForElementVisible("#signInButton")
      .click("#signInButton")
      .waitForElementVisible(".fa-key")
      .click(".fa-key")
      .waitForElementVisible(".passwordProfile__meta")
      .click(".passwordProfile__meta")
      .waitForElementVisible("#site")
      .assert.value("#site", "example.org")
      .assert.value("#login", "contact@example.org");

    browser.end();
  }
};

Fix end to end tests after password profile modifications


SpreeStore.module('StoreApp',function(StoreApp, SpreeStore, Backbone,Marionette,$,_){
  StoreApp.Router = Marionette.AppRouter.extend({
    appRoutes: {
      "products": "listProducts",
      "products/:id": "showProduct",
      "products/page/:number": "listProducts",
      "cart": "previewCart",
      "checkout": "checkout"
    }
  });

  var API = {
    listProducts: function(pageNumber) {
      SpreeStore.Taxonomies.List.Controller.listTaxonomies();
      SpreeStore.Products.List.Controller.listProducts(pageNumber);
    },

    listTaxonomies: function() {
      SpreeStore.Taxonomies.List.Controller.listTaxonomies();
    },

    showProduct: function(id) {
      SpreeStore.Products.Show.Controller.showProduct(id);
    },

    showCartInfo: function() {
      SpreeStore.Cart.Controller.showCartInfo();
    },

    previewCart: function() {
      SpreeStore.Cart.Controller.preview();
    },

    checkout: function() {
      SpreeStore.Order.Controller.show();
    }
  }

  SpreeStore.on("products:list", function() {
    SpreeStore.navigate("products")
    API.listProducts();
    API.listTaxonomies();
  })

  SpreeStore.addInitializer(function() {
    SpreeStore.noSidebar()
    new StoreApp.Router({
      controller: API
    })
    API.showCartInfo();
  })
})

SpreeStore.module('StoreApp',function(StoreApp, SpreeStore, Backbone,Marionette,$,_){
  StoreApp.Router = Marionette.AppRouter.extend({
    appRoutes: {
      "products": "listProducts",
      "products/:id": "showProduct",
      "products/page/:number": "listProducts",
      "cart": "previewCart",
      "checkout": "checkout",
      "checkout/:state": "checkout"
    }
  });

  var API = {
    listProducts: function(pageNumber) {
      SpreeStore.Taxonomies.List.Controller.listTaxonomies();
      SpreeStore.Products.List.Controller.listProducts(pageNumber);
    },

    listTaxonomies: function() {
      SpreeStore.Taxonomies.List.Controller.listTaxonomies();
    },

    showProduct: function(id) {
      SpreeStore.Products.Show.Controller.showProduct(id);
    },

    showCartInfo: function() {
      SpreeStore.Cart.Controller.showCartInfo();
    },

    previewCart: function() {
      SpreeStore.Cart.Controller.preview();
    },

    checkout: function() {
      SpreeStore.Order.Controller.show();
    }
  }

  SpreeStore.on("products:list", function() {
    SpreeStore.navigate("products")
    API.listProducts();
    API.listTaxonomies();
  })

  SpreeStore.addInitializer(function() {
    SpreeStore.noSidebar()
    new StoreApp.Router({
      controller: API
    })
    API.showCartInfo();
  })
})

Add routing for checkout states


/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

const script =
  `
  function __insertWeb3Installed() {
    if (!window.alreadyInserted) {
      const meta = document.createElement('meta')
      meta.name = 'web3-installed'
      document.head.appendChild(meta)
      window.alreadyInserted = true
    }
  }
  if (window.web3) {
    if (!window.web3.currentProvider || !window.web3.currentProvider.isMetaMask) {
      __insertWeb3Installed()
    }
  } else {
    var oldWeb3 = window.web3
    Object.defineProperty(window, 'web3', {
      configurable: true,
      set: function (val) {
        __insertWeb3Installed()
        oldWeb3 = val
      },
      get: function () {
        __insertWeb3Installed()
        return oldWeb3
      }
    })
  }`

if (chrome.contentSettings.dappDetection == 'allow') {
  executeScript(script)
}

setTimeout(function () {
  console.log('checking now for toolbar')
  const isDapp = document.querySelector('meta[name="web3-installed"]')

  if (isDapp) {
    chrome.ipcRenderer.send('dispatch-action', JSON.stringify([{
      actionType: 'app-dapp-available',
      location: window.location.href
    }]))
  }
}, 3000)

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

const script =
  `
  function __insertWeb3Installed() {
    if (!window.alreadyInserted) {
      const meta = document.createElement('meta')
      meta.name = 'web3-installed'
      document.head.appendChild(meta)
      window.alreadyInserted = true
    }
  }
  if (window.web3) {
    if (!window.web3.currentProvider || !window.web3.currentProvider.isMetaMask) {
      __insertWeb3Installed()
    }
  } else {
    var oldWeb3 = window.web3
    Object.defineProperty(window, 'web3', {
      configurable: true,
      set: function (val) {
        __insertWeb3Installed()
        oldWeb3 = val
      },
      get: function () {
        __insertWeb3Installed()
        return oldWeb3
      }
    })
  }`

if (chrome.contentSettings.dappDetection == 'allow') {
  executeScript(script)
}

setTimeout(function () {
  const isDapp = document.querySelector('meta[name="web3-installed"]')
  if (isDapp) {
    chrome.ipcRenderer.send('dispatch-action', JSON.stringify([{
      actionType: 'app-dapp-available',
      location: window.location.href
    }]))
  }
}, 3000)

Remove console.log which isn't needed


'use strict';

// Declare app level module which depends on filters, and services
angular.module('myApp.configuration', [])
  .factory('CORS_PROXY_CFG',function(){
    return {
      enabled: true,
      corsProxifyUrl: function corsProxifyUrl(uri) {
        // return 'http://data.fm/proxy?uri='+encodeURIComponent(uri);
        return 'https://localhost:8443/srv/cors?url='+encodeURIComponent(uri);
      }
    }
  });

;

'use strict';

// Declare app level module which depends on filters, and services
angular.module('myApp.configuration', [])
  .factory('CORS_PROXY_CFG',function(){
    return {
      enabled: true,
      corsProxifyUrl: function corsProxifyUrl(uri) {
        // return 'http://data.fm/proxy?uri='+encodeURIComponent(uri);
        return 'http://localhost:9000/srv/cors?url='+encodeURIComponent(uri);
      }
    }
  });

;

Update cors proxy port number


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

export default {
    entry: path.resolve(__dirname, 'src/index.jsx'),
    output: {
        path: path.join(__dirname),
        filename: 'app.bundle.js'
    },
    module: {
        loaders: [
            {
                test: /\.jsx?$/,
                loader: 'babel',
                exclude: /node_modules/,
                query: {
                    presets: ['es2015', 'stage-0', 'react'],
                    plugins: [
                        'transform-decorators-legacy'
                    ]
                }
            }
        ]
    },
    plugins: [
        new webpack.optimize.UglifyJsPlugin()
    ],
    resolve: {
        extensions: ['', '.js', '.jsx']
    },
    resolveLoader: {
        modulesDirectories: [
            path.resolve(__dirname, 'node_modules'),
            path.resolve(__dirname, '../node_modules')
        ]
    }
};

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

export default {
    entry: path.resolve(__dirname, 'src/index.jsx'),
    output: {
        path: path.join(__dirname),
        filename: 'app.bundle.js'
    },
    module: {
        loaders: [
            {
                test: /\.jsx?$/,
                loader: 'babel',
                exclude: /node_modules/,
                query: {
                    presets: ['es2015', 'stage-0', 'react'],
                    plugins: [
                        'transform-decorators-legacy'
                    ]
                }
            }
        ]
    },
    plugins: [
        new webpack.optimize.UglifyJsPlugin()
    ],
    resolve: {
        extensions: ['', '.js', '.jsx']
    },
    resolveLoader: {
        modulesDirectories: [
            path.resolve(__dirname, 'node_modules')
        ]
    }
};

Remove unnecessary moduleDirectories for resolveLoader


const gulp = require('gulp'),
    browserSync = require('browser-sync').get('PGR2015'),
    inject = require('gulp-inject'),
    modRewrite = require('connect-modrewrite'),
    wiredep = require('wiredep').stream;

module.exports = function () {
    browserSync.init({
        server: {
            baseDir: ['./.tmp'],
            middleware: [
                modRewrite([
                    '^[^\\.]*$ /index.html [L]'
                ])
            ]
        },
        open: false
    });

    gulp.src('app/components/**/*').pipe(gulp.dest('.tmp/components'));

    gulp.src('app/index.html')
        .pipe(inject(gulp.src('.tmp/*.js'), {
            ignorePath: '.tmp/'
        }))
        .pipe(wiredep())
        .pipe(gulp.dest('.tmp'));

    gulp.watch(['app/*.ts', 'app/modules/**/*.ts'], ['ts-watch:serve']);
    gulp.watch(['app/modules/**/*.html'], ['html-watch:serve']);
    gulp.watch(['app/styles/*.scss', 'app/modules/**/*.scss'], ['scss-watch:serve']);
    gulp.watch(['.tmp/*.js', '.tmp/**/*.html'], function () {
        browserSync.reload();
    });
};

const gulp = require('gulp'),
    browserSync = require('browser-sync').get('PGR2015'),
    inject = require('gulp-inject'),
    modRewrite = require('connect-modrewrite'),
    wiredep = require('wiredep').stream;

module.exports = function () {
    browserSync.init({
        server: {
            baseDir: ['./.tmp'],
            middleware: [
                modRewrite([
                    '^[^\\.]*$ /index.html [L]'
                ])
            ]
        },
        open: false,
        https: true
    });

    gulp.src('app/components/**/*').pipe(gulp.dest('.tmp/components'));

    gulp.src('app/index.html')
        .pipe(inject(gulp.src('.tmp/*.js'), {
            ignorePath: '.tmp/'
        }))
        .pipe(wiredep())
        .pipe(gulp.dest('.tmp'));

    gulp.watch(['app/*.ts', 'app/modules/**/*.ts'], ['ts-watch:serve']);
    gulp.watch(['app/modules/**/*.html'], ['html-watch:serve']);
    gulp.watch(['app/styles/*.scss', 'app/modules/**/*.scss'], ['scss-watch:serve']);
    gulp.watch(['.tmp/*.js', '.tmp/**/*.html'], function () {
        browserSync.reload();
    });
};

Enable HTTPS for localhost dev


  $(document).ready(function() {
    $("#id_place")
      .geocomplete({
        map: "#map_location",
        mapOptions: {
          zoom: 10
        },
        markerOptions: {
          draggable: true
        }
        //details: "#id_location"
      })
      .bind("geocode:result", function(event, result){
        console.log("Result: " + result.formatted_address + result.lat + ',' + result.lng);
      })
      .bind("geocode:error", function(event, status){
        console.log("ERROR: " + status);
      })
      .bind("geocode:multiple", function(event, results){
        console.log("Multiple: " + results.length + " results found");
      });
  });

  $(document).ready(function() {
    $("#id_place")
      .geocomplete({
        map: "#map_location",
        mapOptions: {
          zoom: 10
        },
        markerOptions: {
          draggable: true
        }
      })
      .bind("geocode:result", function(event, result) {
        var coordinates = result.geometry.location.lat() + ',' + result.geometry.location.lng();
        $('#id_location').val(coordinates);
      })
      .bind("geocode:error", function(event, status){
        console.log("ERROR: " + status);
      })
      .bind("geocode:multiple", function(event, results){
        console.log("Multiple: " + results.length + " results found");
      });
  });

Set lat and lng values


import { routerStateReducer } from 'redux-router';
import * as types from '../types';

export default () => (state = {}, action) => {
  if (action.type === types.SITE_ID_CHANGED) return { ...state, siteId: action.siteId };
  else if (action.type === types.IS_PREVIEW) return { ...state, preview: true };
  return routerStateReducer(state, action);
};

import { routerStateReducer } from 'redux-router';
import * as types from '../types';

export default () => (state = {}, action) => {
  if (action.type === types.SITE_ID_CHANGED) return { ...state, siteId: action.siteId };
  else if (action.type === types.IS_PREVIEW) return { ...state, preview: true };
  return { ...state, ...routerStateReducer(state, action) };
};

Fix siteIdChanged being triggered twice.


/**
Backend service

This module defines endpoints and access functions the features app REST service
*/

/* window.fetch polyfill */
import 'whatwg-fetch';
import restful, {fetchBackend} from 'restful.js';

/* Configure restful with fetch backend */
const api = restful('/api', fetchBackend(fetch));

const featureCollection = api.all('features');
const featureMember = api.one('features');

export default {
    api,
    endpoints: {
        features: {
            collection: featureCollection,
            member: featureMember
        }
    }
};

/**
Backend service

This module defines endpoints and access functions the features app REST service
*/

/* window.fetch polyfill */
import 'whatwg-fetch';
import restful, {fetchBackend} from 'restful.js';

/* Configure restful with fetch backend */
const api = restful('/api', fetchBackend(fetch));

const featureCollection = api.all('features');
const featureMember = (id) => featureCollection.get(id);

export default {
    api,
    endpoints: {
        features: {
            collection: featureCollection,
            member: featureMember
        }
    }
};

Refactor featureMember to reuse featureCollection


var Tuple = require('tuple-w')

exports.Command = require('./command.js')
exports.Response = require('./response.js')
exports.Controller = require('./controller.js')

var alpha = 'abcdefghjklmnopqrstuvwxyz'

exports.parseCommand = function(input) {
    input = input.replace(/\t/g, ' ').trim()
    var inputs = input.split(' ').filter(function(x) { return x != '' })
    var id = parseInt(inputs[0])

    if (!isNaN(id)) inputs.splice(0, 1)
    var name = inputs[0]
    inputs.splice(0, 1)

    return new exports.Command(id, name, inputs)
}

exports.parseResponse = function(input) {
    input = input.replace(/\t/g, ' ').trim()
    var error = input[0] != '='
    var hasId = input[1] != ' '

    input = input.substr(1)
    var id = hasId ? parseInt(input.split(' ')[0]) : null

    if (hasId) input = input.substr((id + '').length)

    return new exports.Response(id, input.substr(1), error)
}

exports.vertex2point = function(v, size) {
    return alpha[v[0]] + (size - v[1])
}

exports.point2vertex = function(point, size) {
    var x = alpha.indexOf(point[0].toLowerCase())
    var y = size - parseInt(point.substr(1))
    return new Tuple(x, y)
}

var Tuple = require('tuple-w')

exports.Command = require('./command.js')
exports.Response = require('./response.js')
exports.Controller = require('./controller.js')

var alpha = 'abcdefghjklmnopqrstuvwxyz'

exports.parseCommand = function(input) {
    input = input.replace(/\t/g, ' ').trim()
    var inputs = input.split(' ').filter(function(x) { return x != '' })
    var id = parseInt(inputs[0])

    if (!isNaN(id)) inputs.splice(0, 1)
    var name = inputs[0]
    inputs.splice(0, 1)

    return new exports.Command(id, name, inputs)
}

exports.parseResponse = function(input) {
    input = input.replace(/\t/g, ' ').trim()
    var error = input[0] != '='
    var hasId = input[1] != ' '

    input = input.substr(1)
    var id = hasId ? parseInt(input.split(' ')[0]) : null

    if (hasId) input = input.substr((id + '').length)

    return new exports.Response(id, input.substr(1), error)
}

exports.vertex2point = function(v, size) {
    if (v[0] < 0 || v[1] < 0 || v[0] >= size || v[1] >= size)
        return 'pass'
    return alpha[v[0]] + (size - v[1])
}

exports.point2vertex = function(point, size) {
    var x = alpha.indexOf(point[0].toLowerCase())
    var y = size - parseInt(point.substr(1))
    return new Tuple(x, y)
}

Return 'pass' when outside board size


var exec = require('child_process').exec;

var processes = {
  webapp: 'processes/webapp',
  deposits: 'processes/deposits',
  outgoing: 'processes/outgoing',
  incoming: 'processes/incoming',
  withdrawals: 'processes/withdrawals'
};

function startGateway() {
  var command, name;

  for (i in processes) {
    name = processes[i];
    command = 'node '+ name
    processes[i] = exec(command);
    processes[i].stdout.setEncoding('utf8');
    processes[i].stdout.on('data', function(data) {
      console.log(data);
    });
  }

}

module.exports = startGateway;

var exec = require('child_process').exec;

var processes = {
  webapp: 'processes/webapp',
  deposits: 'processes/deposits',
  outgoing: 'processes/outgoing',
  incoming: 'processes/incoming',
  withdrawals: 'processes/withdrawals',
  ripple_rest: 'processes/ripple_rest'
};

function startGateway() {
  var command, name;

  for (i in processes) {
    name = processes[i];
    command = 'node '+ name
    processes[i] = exec(command);
    processes[i].stdout.setEncoding('utf8');
    processes[i].stdout.on('data', function(data) {
      console.log(data);
    });
  }

}

module.exports = startGateway;

Add ripple_rest process to bin/gateway start cli command.


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

module.exports = function (config) {
  var configuration = {
    basePath: '',
    frameworks: ['jasmine', '@angular/cli'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-jasmine-html-reporter'),
      require('karma-coverage-istanbul-reporter'),
      require('@angular/cli/plugins/karma')
    ],
    client:{
      clearContext: false // leave Jasmine Spec Runner output visible in browser
    },
    coverageIstanbulReporter: {
      reports: [ 'html', 'lcovonly' ],
      fixWebpackSourcePaths: true
    },
    angularCli: {
      environment: 'dev'
    },
    reporters: ['progress', 'kjhtml'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    customLaunchers: {
      ChromeHeadless:  {
        base:   'Chrome',
        flags:  [
          '--headless',
          '--disable-gpu',
          '--remote-debugging-port=9222'
        ]
      }
    },
    browsers: ['Chrome'],
    singleRun: false
  };
  if (process.env.TRAVIS) {
    configuration.browsers = ['ChromeHeadless'];
  }

  config.set(configuration);
};

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

module.exports = function (config) {
  var configuration = {
    basePath: '',
    frameworks: ['jasmine', '@angular/cli'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-jasmine-html-reporter'),
      require('karma-coverage-istanbul-reporter'),
      require('@angular/cli/plugins/karma')
    ],
    client:{
      clearContext: false // leave Jasmine Spec Runner output visible in browser
    },
    coverageIstanbulReporter: {
      reports: [ 'html', 'lcovonly' ],
      fixWebpackSourcePaths: true
    },
    angularCli: {
      environment: 'dev'
    },
    reporters: ['progress', 'kjhtml'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    customLaunchers: {
      ChromeHeadless:  {
        base:   'Chrome',
        flags:  [
          '--headless',
          '--disable-gpu',
          '--remote-debugging-port=9222',
          '--no-sandbox'
        ]
      }
    },
    browsers: ['Chrome'],
    singleRun: false
  };
  if (process.env.TRAVIS) {
    configuration.browsers = ['ChromeHeadless'];
  }

  config.set(configuration);
};

Set up Travis test environment (cont.)


cinema.models.LayerModel = Backbone.Model.extend({

    constructor: function (defaults, options) {
        Backbone.Model.call(this, {}, options);
        if (typeof defaults === 'string') {
            this.setFromString(defaults);
        } else if (defaults) {
            this.set('state', defaults);
        }
    },

    /**
     * Convert an object that maps layer identifiers to color-by values into
     * a single string that is consumable by other parts of the application.
     */
    serialize: function () {
        var query = '';

        _.each(this.attributes, function (v, k) {
            query += k + v;
        });

        return query;
    },

    /**
     * Convert a query string to an object that maps layer identifiers to
     * their color-by value. The query string is a sequence of two-character
     * pairs, where the first character identifies the layer ID and the second
     * character identifies which field it should be colored by.
     *
     * The query string is then saved to the model.
     */
    unserialize: function (query) {
        var obj = {};

        if (query.length % 2) {
            return console.error('Query string "' + query + '" has odd length.');
        }

        for (var i = 0; i < query.length; i += 2) {
            obj[query[i]] = query[i + 1];
        }

        return obj;

    },

    /**
     * Set the layers by a "query string".
     */
    setFromString: function (query) {
        var obj = this.unserialize(query);

        this.set('state', obj);
    }
});

cinema.models.LayerModel = Backbone.Model.extend({

    constructor: function (defaults, options) {
        Backbone.Model.call(this, {}, options);
        if (typeof defaults === 'string') {
            this.setFromString(defaults);
        } else if (defaults) {
            this.set('state', defaults);
        }
    },

    /**
     * Convert an object that maps layer identifiers to color-by values into
     * a single string that is consumable by other parts of the application.
     */
    serialize: function () {
        var query = '';

        _.each(this.get('state'), function (v, k) {
            query += k + v;
        });

        return query;
    },

    /**
     * Convert a query string to an object that maps layer identifiers to
     * their color-by value. The query string is a sequence of two-character
     * pairs, where the first character identifies the layer ID and the second
     * character identifies which field it should be colored by.
     *
     * The query string is then saved to the model.
     */
    unserialize: function (query) {
        var obj = {};

        if (query.length % 2) {
            return console.error('Query string "' + query + '" has odd length.');
        }

        for (var i = 0; i < query.length; i += 2) {
            obj[query[i]] = query[i + 1];
        }

        return obj;

    },

    /**
     * Set the layers by a "query string".
     */
    setFromString: function (query) {
        var obj = this.unserialize(query);

        this.set('state', obj);
    }
});

Fix layer model serialize method to use new organization


"use strict";

var React = require('react');

var LeafletMap = require('react-leaflet').Map;
var Marker = require('react-leaflet').Marker;
var Popup = require('react-leaflet').Popup;
var TileLayer = require('react-leaflet').TileLayer;

var TrainsMap = React.createClass({
  getInitialState: function() {
    return {
      lat: 51.505,
      lng: -0.09,
      zoom: 13
    };
  },

  render: function() {
    var position = [this.state.lat, this.state.lng];
    return <LeafletMap center={position} zoom={this.state.zoom}>
      <TileLayer
        url='http://{s}.tile.osm.org/{z}/{x}/{y}.png'
        attribution='© OpenStreetMap contributors'
      />
      <Marker position={position}>
        <Popup>
          A pretty CSS3 popup.
 Easily customizable.
        </Popup>
      </Marker>
    </LeafletMap>;
 }

});

module.exports = TrainsMap;

"use strict";

var React = require('react');

var LeafletMap = require('react-leaflet').Map;
var Marker = require('react-leaflet').Marker;
var Popup = require('react-leaflet').Popup;
var TileLayer = require('react-leaflet').TileLayer;

var TrainsMap = React.createClass({
  getInitialState: function() {
    return {
      lat: 51.505,
      lng: -0.09,
      zoom: 12
    };
  },

  render: function() {
    var position = [this.state.lat, this.state.lng];
    return <LeafletMap center={position} zoom={this.state.zoom}>
      <TileLayer
        url='http://tile.stamen.com/toner/{z}/{x}/{y}.png'
        attribution='Map data © OpenStreetMap contributors, CC-BY-SA, Imagery © Stamen'
      />
    </LeafletMap>;
 }

});

module.exports = TrainsMap;

Use stamen tiles and set middle point.


/*
---

script: Shortcuts.js

description: Add command key listeners to the widget

license: Public domain (http://unlicense.org).

authors: Yaroslaff Fedin

requires:
  - Ext/Shortcuts
  - LSD.Module
  - LSD.Module.Events

provides:
  - LSD.Module.Shortcuts

...
*/
LSD.Module.Shortcuts = new Class({
  Implements: Shortcuts,

  addShortcut: function() {
    LSD.Module.Events.setEventsByRegister.call(this, 'shortcuts', LSD.Module.Shortcuts.events);
    return Shortcuts.prototype.addShortcut.apply(this, arguments);
  },

  removeShortcut: function() {
    LSD.Module.Events.setEventsByRegister.call(this, 'shortcuts', LSD.Module.Shortcuts.events);
    return Shortcuts.prototype.removeShortcut.apply(this, arguments);
  }
});

LSD.Module.Events.addEvents.call(LSD.Module.Shortcuts.prototype, {
  focus: 'enableShortcuts',
  blur: 'disableShortcuts'
});

LSD.Options.shortcuts = {
  add: 'addShortcut',
  remove: 'removeShortcut',
  process: 'bind',
  iterate: true
};

/*
---

script: Shortcuts.js

description: Add command key listeners to the widget

license: Public domain (http://unlicense.org).

authors: Yaroslaff Fedin

requires:
  - Ext/Shortcuts
  - Ext/Element.Events.keypress
  - LSD.Module
  - LSD.Module.Events

provides:
  - LSD.Module.Shortcuts

...
*/
LSD.Module.Shortcuts = new Class({
  Implements: Shortcuts,

  addShortcut: function() {
    LSD.Module.Events.setEventsByRegister.call(this, 'shortcuts', LSD.Module.Shortcuts.events);
    return Shortcuts.prototype.addShortcut.apply(this, arguments);
  },

  removeShortcut: function() {
    LSD.Module.Events.setEventsByRegister.call(this, 'shortcuts', LSD.Module.Shortcuts.events);
    return Shortcuts.prototype.removeShortcut.apply(this, arguments);
  }
});

LSD.Module.Events.addEvents.call(LSD.Module.Shortcuts.prototype, {
  focus: 'enableShortcuts',
  blur: 'disableShortcuts'
});

LSD.Options.shortcuts = {
  add: 'addShortcut',
  remove: 'removeShortcut',
  process: 'bind',
  iterate: true
};

Add dependency on keypress event


'use strict';

import { port } from './config/config';
import app from './app';

import getLogger from './libs/winston';

import { db } from './config/database';

const log = getLogger(module);

let server = app.listen(port, (err) => {
  server.address().port;

  if (err) {
    log.error('something bad happened', err);
  } else {
    db.connect();
  }

  log.info(`server is listening on ${port}`);
});

export default server;

'use strict';

import { port } from './config/config';
import app from './app';

import getLogger from './libs/winston';

import { db } from './config/database';

const log = getLogger(module);

let server = app.listen(port, (err) => {
  server.address().port;

  if (err) {
    log.error('Something bad happened', err);
  } else {
    db.connect();
  }

  log.info(`Server is listening on ${port}`);
});

export default server;

Add logs to trello micro service


"use strict";

module.exports = {

  twitter: {
    consumer_key: "",
    consumer_secret: "",
    access_token: "",
    access_token_secret: ""
  },

  timezone: "Asia/Tokyo",

  excludePrevThemes: true,

  themes: [
    "ココア",
    "チノ",
    "リゼ",
    "千夜",
    "シャロ",
    "マヤ",
    "メグ",
    "青山ブルーマウンテン",
    "モカ"
  ],

  mainThemes: [
    "ココア",
    "チノ",
    "リゼ",
    "千夜",
    "シャロ",
    "マヤ",
    "メグ"
  ],

  subThemes: [
    "凛",
    "タカヒロ",
    "チノ母",
    "ココア母",
    "リゼ父",
    "千夜祖母",
    "メグ母",
    "ティッピー",
    "ワイルドギース",
    "あんこ",
    "吹き矢部の部長",
    "ココア千夜のクラスメイト"
  ],

  characterFree: [],

  wordThemes: {
    words: [],
    date: []
  }

};

"use strict";

module.exports = {

  twitter: {
    consumer_key: process.env.GODB_TWITTER_CONSUMER_KEY,
    consumer_secret: process.env.GODB_TWITTER_CONSUMER_SECRET,
    access_token: process.env.GODB_TWITTER_ACCESS_TOKEN,
    access_token_secret: process.env.GODB_TWITTER_ACCESS_TOKEN_SECRET
  },

  timezone: "Asia/Tokyo",

  excludePrevThemes: true,

  themes: [
    "ココア",
    "チノ",
    "リゼ",
    "千夜",
    "シャロ",
    "マヤ",
    "メグ",
    "青山ブルーマウンテン",
    "モカ"
  ],

  mainThemes: [
    "ココア",
    "チノ",
    "リゼ",
    "千夜",
    "シャロ",
    "マヤ",
    "メグ"
  ],

  subThemes: [
    "凛",
    "タカヒロ",
    "チノ母",
    "ココア母",
    "リゼ父",
    "千夜祖母",
    "メグ母",
    "ティッピー",
    "ワイルドギース",
    "あんこ",
    "吹き矢部の部長",
    "ココア千夜のクラスメイト"
  ],

  characterFree: [],

  wordThemes: {
    words: [],
    date: []
  }

};

Use env vars on default config


'use strict';

const VAL32 = 0xFFFFFFFF;

class BufferUtils {

    static readUInt64BE(buffer, offset) {
        let hi = buffer.readUInt32BE(offset);
        let value = buffer.readUInt32BE(offset + 4);
        if (hi > 0) {
            value += hi * VAL32;
        }
        return value;
    }

    static writeUInt64BE(buffer, value, offset) {
        let hi = 0;
        let lo = value;
        if (value > VAL32) {
            hi = (value / VAL32) << 0;
            lo = value % VAL32;
        }
        buffer.writeUInt32BE(hi, offset);
        buffer.writeUInt32BE(lo, offset + 4);
    }

}

module.exports = BufferUtils;

'use strict';

const VAL32 = 0xFFFFFFFF;

class BufferUtils {

    static readUInt64BE(buffer, offset) {
        let hi = buffer.readUInt32BE(offset);
        let value = buffer.readUInt32BE(offset + 4);
        if (hi > 0) {
            value += hi * (VAL32 + 1);
        }
        return value;
    }

    static writeUInt64BE(buffer, value, offset) {
        let hi = 0;
        let lo = value;
        if (value > VAL32) {
            hi = (value / (VAL32 + 1)) << 0;
            lo = value % (VAL32 + 1);
        }
        buffer.writeUInt32BE(hi, offset);
        buffer.writeUInt32BE(lo, offset + 4);
    }

}

module.exports = BufferUtils;

Fix a bug in BufferUtils


/** @babel */

export default class ChangedFile {
  constructor (oldName, newName, status, hunks) {
    this.newName = newName
    this.oldName = oldName
    this.status = status
    this.hunks = hunks
  }

  getOldFileName () {
    return this.oldName
  }

  getNewFileName () {
    return this.newName
  }

  getStatus () {
    return this.status
  }
}

/** @babel */

export default class ChangedFile {
  constructor (oldName, newName, status, hunks) {
    this.newName = newName
    this.oldName = oldName
    this.status = status
    this.hunks = hunks
  }

  getOldName () {
    return this.oldName
  }

  getNewName () {
    return this.newName
  }

  getStatus () {
    return this.status
  }
}

Rename ChangedFile methods to `getNewName` and `getOldName`


import { inject as service } from '@ember/service';
import { get } from '@ember/object';
import { alias } from '@ember/object/computed';
import Component from '@ember/component';
import ModalBase from 'shared/mixins/modal-base';
import layout from './template';
import { eachLimit } from 'async';

export default Component.extend(ModalBase, {
  growl: service(),

  layout,
  classNames: ['medium-modal'],

  selection: {},

  resources: alias('modalService.modalOpts.resources'),

  actions: {
    drain() {
      const nodeDrainInput = { ...get(this, 'selection') };
      const resources = get(this, 'resources').slice();

      eachLimit(resources, 5, (resource, cb) => {
        if ( !resource ) {
          return cb();
        }

        resource.doAction('drain', nodeDrainInput).finally(cb);
      });

      this.send('cancel');
    },
  },
});

import { inject as service } from '@ember/service';
import { get } from '@ember/object';
import { alias } from '@ember/object/computed';
import Component from '@ember/component';
import ModalBase from 'shared/mixins/modal-base';
import layout from './template';
import { eachLimit } from 'async';

export default Component.extend(ModalBase, {
  growl: service(),

  layout,
  classNames: ['medium-modal'],

  selection: {},

  resources: alias('modalService.modalOpts.resources'),

  init() {
    this._super(...arguments);
    this.selection = {};
  },

  actions: {
    drain() {
      const nodeDrainInput = { ...get(this, 'selection') };
      const resources = get(this, 'resources').slice();

      eachLimit(resources, 5, (resource, cb) => {
        if ( !resource ) {
          return cb();
        }

        resource.doAction('drain', nodeDrainInput).finally(cb);
      });

      this.send('cancel');
    },
  },
});

Reset registry modal step on each open


import React from 'react';
import Reflux from 'reflux';
import Helmet from 'react-helmet';

import Actions from './CustomSocketsActions';
import Store from './CustomSocketsStore';

import { Container, InnerToolbar } from '../../common/';
import CustomSocketsList from './CustomSocketsList';

const CustomSockets = React.createClass({

  mixins: [
    Reflux.connect(Store)
  ],

  componentDidMount() {
    Actions.fetch();
  },

  render() {
    const { items, hideDialogs, isLoading } = this.state;

    return (
      <div>
        <Helmet title="Installed Sockets" />
        <InnerToolbar title="Installed Sockets" />
        <Container>
          <CustomSocketsList
            isLoading={isLoading}
            items={items}
            hideDialogs={hideDialogs}
          />
        </Container>
      </div>
    );
  }
});

export default CustomSockets;

import React from 'react';
import Reflux from 'reflux';
import Helmet from 'react-helmet';

import Actions from './CustomSocketsActions';
import Store from './CustomSocketsStore';

import { Container, InnerToolbar } from '../../common/';
import CustomSocketsList from './CustomSocketsList';

const CustomSockets = React.createClass({

  mixins: [
    Reflux.connect(Store)
  ],

  componentDidMount() {
    Actions.fetch();
  },

  render() {
    const { items, hideDialogs, isLoading } = this.state;

    return (
      <div>
        <Helmet title="My Sockets" />
        <InnerToolbar title="My Sockets" />
        <Container>
          <CustomSocketsList
            isLoading={isLoading}
            items={items}
            hideDialogs={hideDialogs}
          />
        </Container>
      </div>
    );
  }
});

export default CustomSockets;

Change "Installed Sockets" to "My Sockets"


import BSDClient from '../../bsd-instance';

export default function(sequelize, DataTypes) {
  let GCBSDGroup = sequelize.define('GCBSDGroup', {
    query: {
      type: DataTypes.TEXT,
      allowNull: true
    }
  }, {
    underscored: true,
    tableName: 'gc_bsd_groups',
    updatedAt: 'modified_dt',
    createdAt: 'create_dt',
    indexes: [
      { fields: ['cons_group_id'] },
    ],
    classMethods: {
      associate: (models) => {
        GCBSDGroup.belongsTo(models.BSDGroup, {
          foreignKey: 'cons_group_id',
          as: 'BSDGroup',
          constraints: false
        });
        GCBSDGroup.belongsToMany(models.BSDPerson, {
          through: models.BSDPersonGCBSDGroup,
          foreignKey: 'gc_bsd_group_id',
          as: 'people'
        });
      }
    }
  })
  return GCBSDGroup;
}

import BSDClient from '../../bsd-instance';

export default function(sequelize, DataTypes) {
  let GCBSDGroup = sequelize.define('GCBSDGroup', {
    query: {
      type: DataTypes.TEXT,
      allowNull: true
    }
  }, {
    underscored: true,
    tableName: 'gc_bsd_groups',
    updatedAt: 'modified_dt',
    createdAt: 'create_dt',
    indexes: [
      { fields: ['cons_group_id'] },
    ],
    classMethods: {
      associate: (models) => {
        GCBSDGroup.belongsTo(models.BSDGroup, {
          foreignKey: 'cons_group_id',
          as: 'BSDGroup',
          constraints: false
        });
        GCBSDGroup.belongsToMany(models.BSDPerson, {
          through: models.BSDPersonGCBSDGroup,
          foreignKey: 'gc_bsd_group_id',
          as: 'people',
          constraints: false
        });
      }
    }
  })
  return GCBSDGroup;
}

Fix constraint problem for real. Another sequelize bug


/**
 * Created by CCristi <ccovali@mitocgroup.com> on 12/10/15.
 */

'use strict';

export class Context {
  /**
   * @param {Object} options
   */
  constructor(options) {
    this._options = options;

    this._registerDataAsOptions();
  }

  /**
   * @returns {Object}
   */
  get options() {
    return this._options;
  }

  /**
   * @private
   */
  _registerDataAsOptions() {
    for (let key in this._options) {
      if (!this._options.hasOwnProperty(key)) {
        continue;
      }

      Object.defineProperty(this, key, {
        value: this._options[key],
        writable: false,
        configurable: false,
        enumerable: true,
      });
    }

    // Avoid _data key listing on Object.keys(request)
    Object.defineProperty(this, '_options', {
      configurable: false,
    });
  }

  /**
   * @param {String} option
   * @returns {boolean}
   */
  has(option) {
    return this._options.hasOwnProperty(option);
  }

  /**
   * @param {String} option
   * @param {*} defaultValue
   * @returns {*}
   */
  getOption(option, defaultValue = undefined) {
    return this._options.hasOwnProperty(option) ? this._options[option] : defaultValue;
  }
}

/**
 * Created by CCristi <ccovali@mitocgroup.com> on 12/10/15.
 */

'use strict';

export class Context {
  /**
   * @param {Object} options
   */
  constructor(options) {
    this._options = options;

    this._registerDataAsOptions();
  }

  /**
   * @returns {Object}
   */
  get options() {
    return this._options;
  }

  /**
   * @private
   */
  _registerDataAsOptions() {
    for (let key in this._options) {
      if (!this._options.hasOwnProperty(key)) {
        continue;
      }

      Object.defineProperty(this, key, {
        value: this._options[key],
        writable: false,
        configurable: false,
        enumerable: true,
      });
    }

    // Avoid _data key listing on Object.keys(request)
    Object.defineProperty(this, '_options', {
      configurable: false,
      enumerable: false,
    });
  }

  /**
   * @param {String} option
   * @returns {boolean}
   */
  has(option) {
    return this._options.hasOwnProperty(option);
  }

  /**
   * @param {String} option
   * @param {*} defaultValue
   * @returns {*}
   */
  getOption(option, defaultValue = undefined) {
    return this._options.hasOwnProperty(option) ? this._options[option] : defaultValue;
  }
}

Make _options prop from lambda context not enumerable


const Join = () => {
  return (

Bli med i linjeforeningen!

Alle informatikere er med i linjeforeningen. Gå videre til hovedsiden for å lage din brukerkonto på Online sine systemer.

Har du lyst til å gjøre studietiden til informatikere enda bedre? Som komitemedlem i Online blir du del av en familie du aldri vil glemme. Vi tilbyr utfordrende og spennende verv i et meget sosialt miljø med stor takhøyde.

Les mer om de ulike komiteene, linjeforeningen og mye mer på vår Wiki.

  );
};

export default Join;

Add className to join component


var gulp   = require("gulp");
var CFG    = require("./utils/config.js");
var $      = require("gulp-load-plugins")();
var exec   = require("child_process").exec;
var path   = require("path");
var notify = require("./utils/notify-style-lint");

/**
 * style:lint
 * @see github.com/causes/scss-lint
 * @see rubygems.org/gems/scss-lint
 */
gulp.task("style:lint", function (callback) {
  var scsslintProcess = exec("bundle " + [
    "exec",
    "scss-lint",
    "--config",
    path.join(CFG.FILE.config.styleLint),
    path.join(CFG.DIR.src, CFG.DIR.style)
  ].join(" "), function(err, stdout, stderr) {
    $.util.log("[style:lint] stdout:", stdout);
    $.util.log("[style:lint] stderr: ", stderr);

    notify(stdout);

    if(null !== err) {
      $.util.log("[style:lint] err: ", err);
    }

    callback();
  });
});

var gulp   = require("gulp");
var CFG    = require("./utils/config.js");
var $      = require("gulp-load-plugins")();
var exec   = require("child_process").exec;
var path   = require("path");
var notify = require("./utils/notify-style-lint");

/**
 * style:lint
 * @see github.com/causes/scss-lint
 * @see rubygems.org/gems/scss-lint
 */
gulp.task("style:lint", function (callback) {
  var scsslintProcess = exec([
    "bundle",
    "exec",
    "scss-lint",
    "--config",
    path.join(CFG.FILE.config.styleLint),
    path.join(CFG.DIR.src, CFG.DIR.style)
  ].join(" "), function(err, stdout, stderr) {
    $.util.log("[style:lint] stdout:", stdout);
    $.util.log("[style:lint] stderr: ", stderr);

    notify(stdout);

    if(null !== err) {
      $.util.log("[style:lint] err: ", err);
    }

    callback();
  });
});

Simplify arguments passed to exec.


import React from 'react'
import { StackNavigator } from 'react-navigation'
import Home from './stateless/screens/Home'
import ReposList from './stateless/screens/ReposList'
// import SEARCH_QUERY from './stateless/screens/Home'

const Router = StackNavigator({
  Home: { screen: Home },
  ReposList: { screen: props => <ReposList {...props} searchQuery="react" /> }
  // ContributorsList: { ContributorsList }
})

export default Router

import React from 'react'
import { StackNavigator } from 'react-navigation'
import Home from './stateless/screens/Home'
import ReposList from './stateless/screens/ReposList'
import { SEARCH_QUERY } from './stateless/screens/Home'

const Router = StackNavigator({
  Home: { screen: Home },
  ReposList: { screen: props => <ReposList {...props} searchQuery={SEARCH_QUERY} /> }
  // ContributorsList: { ContributorsList }
})

export default Router

Fix prop returning class instead of value of prop


var YAHOO = require('../../../../src/geo/geocoder/yahoo-geocoder');

describe('geo/geocoder/yahoo-geocoder', function () {
  var originalTimeout;
  beforeEach(function () {
    originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
    jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
  });

  afterEach(function () {
    jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;
  });

  it("we shouldn't get a direction that doesn't exist", function (done) {
    YAHOO.geocode('68461092610314965639', function (d) {
      expect(d.length).toEqual(0);
      done();
    });
  });
});

var YAHOO = require('../../../../src/geo/geocoder/yahoo-geocoder');

describe('geo/geocoder/yahoo-geocoder', function () {
  it("we shouldn't get a direction that doesn't exist", function (done) {
    YAHOO.geocode('68461092610314965639', function (d) {
      expect(d.length).toEqual(0);
      done();
    });
  });
});

Revert "Increase default timeout for yahoo geocoder."


var saikuWidgetComponent = BaseComponent.extend({

	update : function() {
		var myself=this;
		var htmlId = "#" + myself.htmlObject;
		if (myself.saikuFilePath.substr(0,1) == "/") {
			myself.saikuFilePath = myself.saikuFilePath.substr(1,myself.saikuFilePath.length - 1 );
		}

		var parameters = {};
		if (myself.parameters) {
			_.each(myself.parameters, function(parameter) {
				var k = parameter[0];
				var v = parameter[1];

				if (window.hasOwnProperty(v)) {
					v = window[v];
				}
				parameters[k] = v;
			});
		}
		if (myself.width) {
			$(htmlId).width(myself.width);
		}
		if (myself.width) {
			$(htmlId).height(myself.height);
		}
		if ("table" == myself.renderMode) {
			$(htmlId).addClass('workspace_results');
			var t = $("

");
			$(htmlId).html(t);
			htmlId = t;
		}
		var myClient = new SaikuClient({
		    server: "../../../plugin/saiku/api",
		    path: "/cde-component"
		});

		myClient.execute({
		    file: myself.saikuFilePath,
		    htmlObject: htmlId,
		    render: myself.renderMode,
		    mode: myself.renderType,
		    zoom: true,
		    params: parameters
		});

	}
});

var saikuWidgetComponent = BaseComponent.extend({

	update : function() {
		var myself=this;
		var htmlId = "#" + myself.htmlObject;
		if (myself.saikuFilePath.substr(0,1) == "/") {
			myself.saikuFilePath = myself.saikuFilePath.substr(1,myself.saikuFilePath.length - 1 );
		}

		var parameters = {};
		if (myself.parameters) {
			_.each(myself.parameters, function(parameter) {
				var k = parameter[0];
				var v = parameter[1];

				if (window.hasOwnProperty(v)) {
					v = window[v];
				}
				parameters[k] = v;
			});
		}
		if (myself.width) {
			$(htmlId).width(myself.width);
		}
		if (myself.width) {
			$(htmlId).height(myself.height);
		}
		if ("table" == myself.renderMode) {
			$(htmlId).addClass('workspace_results');
			var t = $("

");
			$(htmlId).html(t);
			htmlId = t;
		}
		var myClient = new SaikuClient({
		    server: "/pentaho/plugin/saiku/api",
		    path: "/cde-component"
		});

		myClient.execute({
		    file: myself.saikuFilePath,
		    htmlObject: htmlId,
		    render: myself.renderMode,
		    mode: myself.renderType,
		    zoom: true,
		    params: parameters
		});

	}
});

Use full path to api in stead of relatieve path


// @flow

import Pinentry from './index.render'
import type {DumbComponentMap} from '../constants/types/more'
import type {Props} from './index.render'

const propsNormal: Props = {
  onSubmit: (passphrase, features) => console.log('Pinentry', {passphrase, features}),
  onCancel: () => {},
  features: {
    'saveInKeychain': {
      allow: true,
      defaultValue: false,
      readonly: false,
      label: 'Save in keychain'
    },
    'showTyping': {
      allow: true,
      defaultValue: false,
      readonly: false,
      label: 'Show typing'
    }
  },
  prompt: 'Enter your passphrase to unlock the secret key for home computer.',
  retryLabel: 'That passphrase is incorrect.'
}

const dumbComponentMap: DumbComponentMap<Pinentry> = {
  component: Pinentry,
  mocks: {
    'Normal': propsNormal,
    'Show Typing': {
      ...propsNormal,
      features: {
        ...propsNormal.features,
        'showTyping': {
          ...propsNormal.features.showTyping,
          defaultValue: true
        }
      }
    }
  }
}

export default {
  'Pinentry': dumbComponentMap
}

Add Pinentry dumb component demo to sheet


'use strict';

var computeLayout = require('./Layout');

/**
 * This computes the CSS layout for a RenderLayer tree and mutates the frame
 * objects at each node.
 *
 * @param {Renderlayer} root
 * @return {Object}
 */
function layoutNode (root) {
  var rootNode = createNode(root);
  computeLayout(rootNode);
  walkNode(rootNode);
  return rootNode;
}

function createNode (layer) {
  return {
    layer: layer,
    layout: {
      width: undefined, // computeLayout will mutate
      height: undefined, // computeLayout will mutate
      top: 0,
      left: 0,
    },
    style: layer._originalStyle || {},
    children: (layer.children || []).map(createNode)
  };
}

function walkNode (node, parentLeft, parentTop) {
  node.layer.frame.x = node.layout.left + (parentLeft || 0);
  node.layer.frame.y = node.layout.top + (parentTop || 0);
  node.layer.frame.width = node.layout.width;
  node.layer.frame.height = node.layout.height;
  if (node.children && node.children.length > 0) {
    node.children.forEach(function (child) {
      walkNode(child, node.layout.left, node.layout.top);
    });
  }
}

module.exports = layoutNode;

'use strict';

var computeLayout = require('./Layout');

/**
 * This computes the CSS layout for a RenderLayer tree and mutates the frame
 * objects at each node.
 *
 * @param {Renderlayer} root
 * @return {Object}
 */
function layoutNode (root) {
  var rootNode = createNode(root);
  computeLayout(rootNode);
  walkNode(rootNode);
  return rootNode;
}

function createNode (layer) {
  return {
    layer: layer,
    layout: {
      width: undefined, // computeLayout will mutate
      height: undefined, // computeLayout will mutate
      top: 0,
      left: 0,
    },
    style: layer._originalStyle || {},
    children: (layer.children || []).map(createNode)
  };
}

function walkNode (node, parentLeft, parentTop) {
  node.layer.frame.x = node.layout.left + (parentLeft || 0);
  node.layer.frame.y = node.layout.top + (parentTop || 0);
  node.layer.frame.width = node.layout.width;
  node.layer.frame.height = node.layout.height;
  if (node.children && node.children.length > 0) {
    node.children.forEach(function (child) {
      walkNode(child, node.layer.frame.x, node.layer.frame.y);
    });
  }
}

module.exports = layoutNode;

Fix parent position when walking child nodes


/* $This file is distributed under the terms of the license in /doc/license.txt$ */

$(document).ready(function(){

    // login form is hidden by default; use JavaScript to reveal
    $("#login").removeClass('hidden');

    // focus on email or newpassword field
    $('.focus').focus();

    // fade in error alerts
    $('section#error-alert').css('display', 'none').fadeIn(1500);

    // fade in fash-message when user log out
    $('section#flash-message').css('display', 'none').fadeIn(1500);

});

/* $This file is distributed under the terms of the license in /doc/license.txt$ */

$(document).ready(function(){

    // login form is hidden by default; use JavaScript to reveal
    $("#login").removeClass('hidden');

    // focus on email or newpassword field
    $('.focus').focus();

    // fade in error alerts
    $('section#error-alert').css('display', 'none').fadeIn(1500);

    // fade in fash-message when user log out
    $('section#flash-message').css('display', 'none').fadeIn(1500);

    // fade out flash-message when user logs in
    $('section#welcome-message').css('display', 'block').delay(2500).fadeOut(1500);

});

Update to fade out the welcome log in message


'use strict';
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, IndexRoute, hashHistory, browserHistory } from 'react-router'

// Route-specific views:
import Home from './components/Home';
import About from './components/About';
import Focus from './components/Focus';
import Contact from './components/Contact';
import Error404 from './components/Error404';

// Route-invariant site layout views:
import NavBar from './components/NavBar';
import MainLayout from './components/MainLayout';

// Top-level React (pure functional) component:
const App = () => (
  <Router history={ hashHistory }>
    <Route path='/' component={ MainLayout }>
      <IndexRoute component={ Home } />
      <Route path='/about' component={ About } />
      <Route path='/focus' component={ Focus } />
      <Route path='/contact' component={ Contact } />
      <Route path='*' component={ NotFound } />
    </Route>
  </Router>
);

export default App;

'use strict';
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, IndexRoute, hashHistory, browserHistory } from 'react-router'

// Route-specific views:
import Home from './components/Home';
import About from './components/About';
import Focus from './components/Focus';
import Contact from './components/Contact';
import Error404 from './components/Error404';

// Route-invariant site layout views:
import NavBar from './components/NavBar';
import MainLayout from './components/MainLayout';

// Top-level React (pure functional) component:
const App = () => (
  <Router history={ hashHistory }>
    <Route path='/' component={ MainLayout }>
      <IndexRoute component={ Home } />
      <Route path='/about' component={ About } />
      <Route path='/focus' component={ Focus } />
      <Route path='/contact' component={ Contact } />
      <Route path='*' component={ Error404 } />
    </Route>
  </Router>
);

export default App;

Replace NotFound route component with Error404 component


'use strict';

/**
 * Module dependencies.
 */
//process.env.NODE_ENV = "production";
let Arrow = require('../..');

let application = new Arrow();

global.Arrow = application;

//application.before(require('./core_route'));
//application.config();

application.listen(3333, function () {
    console.log('Application started on port ' + 3333, ', Process ID: ' + process.pid);
});

module.exports = application;

'use strict';

/**
 * Module dependencies.
 */
let Arrow = require('../..');

let application = new Arrow();

global.Arrow = application;

const port = 8000;
application.listen(port, function () {
    console.log('Application started on port ' + port, ', Process ID: ' + process.pid);
});

module.exports = application;

Make HelloWorld app look better


app.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
    var rp = $routeProvider;

    rp.when('/', {
        templateUrl: '/html/home.html',
        controller: 'HomeCtrl',
    });

    rp.otherwise({
        redirectTo: '/'
    });

    $locationProvider.html5Mode({
        enabled: true,
        requireBase: false
    });
}]);

Add a $routeProvider and the $locationProvider


app.config(function($stateProvider){
  $stateProvider.state('explorerState', {
    url: '/',
    templateUrl: './app/explorer/explorer.html',
    controller: 'Explorer'
  })
})

app.config(function($stateProvider){
  $stateProvider.state('explorerState', {
    url: '/',
    templateUrl: './app/explorer/explorer.html',
    controller: 'ExplorerCtrl'
  })
})

Append Ctrl to controller name


import { expect } from 'chai'
import { h, render, rerender } from 'preact'
import App from '../app/components/app'

// describe('App', () => {
//     let scratch

//     before( () => {
//         scratch = document.createElement('div');
//         (document.body || document.documentElement).appendChild(scratch)
//     })

//     beforeEach( () => {
//         scratch.innerHTML = ''
//     })

//     after( () => {
//         scratch.parentNode.removeChild(scratch)
//         scratch = null
//     })

//     describe('routing', () => {
//         it('should render the discovery page', () => {
//             render(<App konnectors={[]}/>, scratch)
//             route('/')
//             expect(scratch.querySelector('main').innerHTML).to.contain('Discovery')
//         })

//         it('should render /category', () => {
//             render(<App konnectors={[]}/>, scratch)
//             route('/category')
//             //rerender()
//             expect(scratch.querySelector('main').innerHTML).to.contain('All accounts')
//         })
//     })
// })

import { expect } from 'chai'
import { h, render, rerender } from 'preact'
import App from '../app/components/App'

// describe('App', () => {
//     let scratch

//     before( () => {
//         scratch = document.createElement('div');
//         (document.body || document.documentElement).appendChild(scratch)
//     })

//     beforeEach( () => {
//         scratch.innerHTML = ''
//     })

//     after( () => {
//         scratch.parentNode.removeChild(scratch)
//         scratch = null
//     })

//     describe('routing', () => {
//         it('should render the discovery page', () => {
//             render(<App konnectors={[]}/>, scratch)
//             route('/')
//             expect(scratch.querySelector('main').innerHTML).to.contain('Discovery')
//         })

//         it('should render /category', () => {
//             render(<App konnectors={[]}/>, scratch)
//             route('/category')
//             //rerender()
//             expect(scratch.querySelector('main').innerHTML).to.contain('All accounts')
//         })
//     })
// })

Fix a typo in an import


/**
 * ReactCompass - a carefully crafted Compass component for React.
 *
 * Copyright (c) 2016 Bohdan Shtepan
 * http://modern-dev.com/
 *
 * Licensed under the MIT license.
 */

module.exports = [
    {
        test: /(\.jsx|\.js)$/,
        preLoaders: ['eslint-loader'],
        loaders: ['babel-loader'],
        exclude: /(node_modules|bower_components)/
    }
];

/**
 * ReactCompass - a carefully crafted Compass component for React.
 *
 * Copyright (c) 2016 Bohdan Shtepan
 * http://modern-dev.com/
 *
 * Licensed under the MIT license.
 */

module.exports = [
    {
        test: /(\.jsx|\.js)$/,
        loader: 'babel-loader',
        exclude: /(node_modules|bower_components)/
    },
    {
        test: /(\.jsx|\.js)$/,
        loader: 'eslint-loader',
        exclude: /(node_modules|bower_components|example|dist)/
    }
];

Configure shity webpack to lint the code exactly before babel would run.


var passport = require('passport')
var util = require('util')
var crypto = require('crypto')
var db = require('mongo-promise')
db.shortcut('clients')

function ClientKeyStrategy() {
  this.name = 'client-key'
};

util.inherits(ClientKeyStrategy, passport.Strategy)

ClientKeyStrategy.prototype.authenticate = function(req, options) {

  var authId = req.param('authId')
  var authHash = req.param('authHash')
  var authTimestamp = req.param('authTimestamp')

  if (!authId || !authHash || !authTimestamp) return this.fail()

  db.clients.find({ authId: authId }).then(function(clients) {
    var client = clients[0]
    if (!client || crypto.createHash('md5').update(authTimestamp).update(client.authSecret).digest('hex') != authHash) {
      return this.fail()
    }
    req.user = client
    this.pass()
  }.bind(this))
};

module.exports = ClientKeyStrategy;

Update hashing to match eagel eye


'use strict';

exports.filterPlatforms = filterPlatforms;
function filterPlatforms(platform) {
  var browser = platform.browserName;
  var version = platform.version;
  if (version === 'dev' || version === 'beta') return false;
  version = +version;
  if (browser === 'chrome') {
    return version >= 53 || version % 5 === 0;
  }
  if (browser === 'firefox') {
    return version >= 30 || version % 5 === 0 || version === 3.6;
  }
  return true;
}

exports.choosePlatforms = choosePlatforms;
function choosePlatforms(platforms) {
  return [platforms[Math.floor(Math.random() * platforms.length)]];
}

'use strict';

exports.filterPlatforms = filterPlatforms;
function filterPlatforms(platform) {
  var browser = platform.browserName;
  var version = platform.version;
  if (version === 'dev' || version === 'beta') return false;
  version = +version;
  if (browser === 'chrome') {
    return version >= 53 || version % 5 === 0;
  }
  if (browser === 'firefox') {
    return version >= 47 || version % 5 === 0 || version === 3.6;
  }
  return true;
}

exports.choosePlatforms = choosePlatforms;
function choosePlatforms(platforms) {
  return [platforms[Math.floor(Math.random() * platforms.length)]];
}

Test a less excessive number of firefox versions by default


module.exports = {
  debug: false,
  //TODO Switch to 'rethinkdb' before pushing
  cmd: '/home/michel/projects/rethinkdb-all/rethinkdb/build/debug/rethinkdb',//'rethinkdb';
  dataDir: 'rethinkdbdash_datadir',
  initialOffset: 180,
  feedQuery: 'r.db("rethinkdb")\n .table("server_status")\n .union(["feedSeparator"])\n .union(r.db("rethinkdb").table("server_status").changes())',
  numServers: 3,
  buffer: 12,
  max: 36
}

module.exports = {
  debug: false,
  cmd: 'rethinkdb',
  dataDir: 'rethinkdbdash_datadir',
  initialOffset: 180,
  feedQuery: 'r.db("rethinkdb")\n .table("server_status")\n .union(["feedSeparator"])\n .union(r.db("rethinkdb").table("server_status").changes())',
  numServers: 3,
  buffer: 12,
  max: 36
}

Revert to rethinkdb instead of personal path


/* eslint-env node */
'use strict';

module.exports = {
  allowedVersions: {
    'ember-get-config': '^0.2.0', // workaround for dep. conflict ember-cli-mirage/ember-light-table
    'ember-getowner-polyfill': '^1.0.0 || ^2.0.0',
    'ember-inflector': '^1.0.0 || ^2.0.0',
    'ember-hash-helper-polyfill': '^0.1.2 || ^0.2.0', // workaround for dep. conflict ember-tooltips/liquid-fire
    'ember-require-module': '^0.1.2 || ^0.2.0' // workaround for dep. conflict ember-cp-validations/ember-validators
  }
};

/* eslint-env node */
'use strict';

module.exports = {
  allowedVersions: {
    'ember-get-config': '^0.2.0', // workaround for dep. conflict ember-cli-mirage/ember-light-table
    'ember-getowner-polyfill': '^1.0.0 || ^2.0.0',
    'ember-inflector': '^1.0.0 || ^2.0.0',
    'ember-hash-helper-polyfill': '^0.1.2 || ^0.2.0', // workaround for dep. conflict ember-tooltips/liquid-fire
    'ember-require-module': '^0.1.2 || ^0.2.0', // workaround for dep. conflict ember-cp-validations/ember-validators
    'ember-compatibility-helpers': '^0.1.3 || ^1.0.0-beta.2' // workaround for dep. conflict ember-light-table/ember-data
  }
};

Add dependency lint exception for ember-compatibility-helpers


import {combineReducers} from "redux";

import entitiesReducer from "./entitiesReducer";
import tabReducer from "features/tabs/tabReducer";
import unitInfoReducer from "features/unitInfo/unitInfoReducer";
import pilotsReducer from "features/pilots/pilotsReducer";
import mechsReducer from "features/mechs/mechsReducer";

const rootReducer = combineReducers({
    entities : entitiesReducer,
    unitInfo : unitInfoReducer,
    pilots : pilotsReducer,
    mechs : mechsReducer,
    tabs : tabReducer,
});

export default rootReducer;

import {combineReducers} from "redux";

import {reduceReducers} from "common/utils/reducerUtils";

import entitiesReducer from "./entitiesReducer";
import tabReducer from "features/tabs/tabReducer";
import unitInfoReducer from "features/unitInfo/unitInfoReducer";
import pilotsReducer from "features/pilots/pilotsReducer";
import mechsReducer from "features/mechs/mechsReducer";

const combinedReducer = combineReducers({
    entities : entitiesReducer,
    unitInfo : unitInfoReducer,
    pilots : pilotsReducer,
    mechs : mechsReducer,
    tabs : tabReducer,
});

const rootReducer = reduceReducers(
    combinedReducer,
);

export default rootReducer;

Update root reducer to wrap around combined reducer


// @flow

import Persister from '../../units/urb-persister-cassandra/graphql/PersisterCassandra'

const defaultPersister = new Persister( )
export default defaultPersister

// @flow

import Persister from '../../units/urb-persister-memory/graphql/PersisterMemory'

const defaultPersister = new Persister()
export default defaultPersister

Change default persister to memory


express = require("express");
cim = require("../index");

var console = cim("APP");

app = express();

app.listen(8080, function(){
  console.log("now listening on port %d", 8080);
});

app.get("/", function(req, res) {
  var console = cim("root", console);
  console.log("Request");
  res.send('sub');
});

app.get("/sub", function(req, res) {
  var console = cim("sub", console);
  console.log("Request");
  res.send('root');
});

express = require("express");
cim = require("../index");

var console = cim("APP");

app = express();

app.listen(8080, function(){
  console.log("now listening on port %d", 8080);
});

app.get("/", function(req, res) {
  var logger = cim("root", console);
  logger.log("Request");
  res.send('sub');
});

app.get("/sub", function(req, res) {
  var logger = cim("sub", console);
  logger.log("Request");
  res.send('root');
});

Fix hoisting mistake in the example


import getPetitionAuthor from 'helpers/getPetitionAuthor';
import getPetitionMetrics from './petitionMetrics';

export default (petition = {}) => {
  if (!petition || !petition.id) {
    return {};
  }

  return {
    id: petition.id,
    link: `/petitions/${petition.id}`,
    title: petition.title,
    footer: {
      info: {
        city: petition.city,
        owner: getPetitionAuthor(petition.owner)
      },
      metrics: getPetitionMetrics(petition)
    }
  };
};

import getPetitionAuthor from 'helpers/getPetitionAuthor';
import getPetitionMetrics from './petitionMetrics';

export default (petition = {}) => {
  if (!petition || !petition.id) {
    return {};
  }

  return {
    id: petition.id,
    link: `/petitions/${petition.id}`,
    title: petition.title,
    footer: {
      info: {
        city: petition.city,
        owner: getPetitionAuthor(petition.owner || {})
      },
      metrics: getPetitionMetrics(petition)
    }
  };
};

Fix broken Teaser author logic


// Karma configuration

// base path, that will be used to resolve files and exclude
basePath = '';

// list of files / patterns to load in the browser
files = [
  JASMINE,
  JASMINE_ADAPTER,
  'components/underscore/underscore.js',
  'components/jquery/jquery.js',
  'src/*.coffee',
  'src/**/*.js',
  'test/mock/**/*.js',
  'test/spec/**/*.coffee'
];

// list of files to exclude
exclude = [];

// test results reporter to use
// possible values: dots || progress || growl
reporters = ['progress'];

// web server port
port = 8080;

// cli runner port
runnerPort = 9100;

// enable / disable colors in the output (reporters and logs)
colors = true;

// level of logging
// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
logLevel = LOG_INFO;

// enable / disable watching file and executing tests whenever any file changes
autoWatch = false;

// Start these browsers, currently available:
// - Chrome
// - ChromeCanary
// - Firefox
// - Opera
// - Safari (only Mac)
// - PhantomJS
// - IE (only Windows)
browsers = ['PhantomJS'];

// If browser does not capture in given timeout [ms], kill it
captureTimeout = 10000;

// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun = false;

// Karma configuration

// base path, that will be used to resolve files and exclude
basePath = '';

// list of files / patterns to load in the browser
files = [
  JASMINE,
  JASMINE_ADAPTER,
  'bower_components/underscore/underscore.js',
  'bower_components/jquery/jquery.js',
  'src/*.coffee',
  'src/**/*.js',
  'test/mock/**/*.js',
  'test/spec/**/*.coffee'
];

// list of files to exclude
exclude = [];

// test results reporter to use
// possible values: dots || progress || growl
reporters = ['progress'];

// web server port
port = 8080;

// cli runner port
runnerPort = 9100;

// enable / disable colors in the output (reporters and logs)
colors = true;

// level of logging
// possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG
logLevel = LOG_INFO;

// enable / disable watching file and executing tests whenever any file changes
autoWatch = false;

// Start these browsers, currently available:
// - Chrome
// - ChromeCanary
// - Firefox
// - Opera
// - Safari (only Mac)
// - PhantomJS
// - IE (only Windows)
browsers = ['PhantomJS'];

// If browser does not capture in given timeout [ms], kill it
captureTimeout = 10000;

// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun = false;

Change components to bower_components for bower 1.0.0


exports = module.exports = function() {
  var Client = require('./internals/client');

  var client = new Client();
  return client;
}

exports['@provides'] = 'io.modulate.www.Client';
exports['@require'] = [];
exports['@singleton'] = true;

exports = module.exports = function() {
  var Client = require('./internals/client');

  var client = new Client();

  // FIXME: Errors if these are commented out
  client.use('http:', require('./internals/protocols/http'));
  client.use('https:', require('./internals/protocols/http'));

  return client;
}

exports['@provides'] = 'io.modulate.www.Client';
exports['@require'] = [];
exports['@singleton'] = true;

Use HTTP protocol by default.


/**
  Errors
  @description defines custom errors used for the middleware
  @exports {class} APIError
**/

/**
  @class APIError
  @desc given when API response gives error outside of 200 range
  @param {number} status HTTP Status given in response
  @param {string} data message given along with the error
  @param {object} response
**/
export class APIError extends Error {
  constructor(status, data, response) {
    super();
    this.name = 'APIError';
    this.status = status;
    this.statusText = data;
    this.data = data;
    this.response = response;
    this.message = `${status} - ${data}`;
  }
}

/**
  @class CallProcessingError
  @desc given when an error occurs while processing the remote call action
  @param {string} msg
  @param {string} processStep the part of the call process that threw the error
  @param {error} sourceError (optional)
**/
export class CallProcessingError extends Error {
  constructor(msg, processStep, sourceError) {
    super();
    this.name = 'CallProcessingError';
    this.processStep = processStep;
    this.sourceError = sourceError;
    this.message = sourceError
      ? `${msg}\nOriginal Error: ${sourceError}`
      : msg;
  }
}

/**
  Errors
  @description defines custom errors used for the middleware
  @exports {class} APIError
**/

/**
  @class APIError
  @desc given when API response gives error outside of 200 range
  @param {number} status HTTP Status given in response
  @param {string} message message given along with the error
  @param {object} response
**/
export class APIError extends Error {
  constructor(status, message, response) {
    super();
    this.name = 'APIError';
    this.status = status;
    this.statusText = message;
    this.response = response;
    this.message = `${status} - ${message}`;
  }
}

/**
  @class CallProcessingError
  @desc given when an error occurs while processing the remote call action
  @param {string} msg
  @param {string} processStep the part of the call process that threw the error
  @param {error} sourceError (optional)
**/
export class CallProcessingError extends Error {
  constructor(msg, processStep, sourceError) {
    super();
    this.name = 'CallProcessingError';
    this.processStep = processStep;
    this.sourceError = sourceError;
    this.message = sourceError
      ? `${msg}\nOriginal Error: ${sourceError}`
      : msg;
  }
}

Use message as param name


export default {
  testEnvironment: 'jsdom',
  // Display coverage summary below file-by-file coverage breakdown
  coverageReporters: ['clover', 'json', 'lcov', 'html', 'text', 'text-summary'],
  transform: {
    '\\.js$': ['rollup-jest'],
    '\\.pegjs$': ['pegjs-jest-transformer']
  }
};

export default {
  testEnvironment: 'jsdom',
  // Display coverage summary below file-by-file coverage breakdown
  coverageReporters: ['clover', 'json', 'lcov', 'html', 'text', 'text-summary'],
  transform: {
    '\\.js$': ['rollup-jest'],
    '\\.pegjs$': ['pegjs-jest-transformer']
  },
  coveragePathIgnorePatterns: ['\\.pegjs']
};

Exclude PegJS grammar from code coverage


import resolve from "rollup-plugin-node-resolve";
import commonjs from "rollup-plugin-commonjs";

export default {
  input: "index.js",
  output: {
    file: "dist/d3-dag.js",
    format: "umd",
    name: "d3",
  },
  plugins: [
    resolve(),
    commonjs(),
  ],
};

import resolve from "rollup-plugin-node-resolve";
import commonjs from "rollup-plugin-commonjs";

export default {
  input: "index.js",
  output: {
    file: "dist/d3-dag.js",
    format: "umd",
    name: "d3",
    extend: true,
  },
  plugins: [
    resolve(),
    commonjs(),
  ],
};

Change rollup to extend d3


(function() {
  var templates = {
    "name": "javascript",
    "context": "javascript",
    "templates": [{
      "name": "properties",
      "description": "With LayoutData containing `left`, `top` and `right` arguments.",
      "template": "{layoutData: {left: 0, top: 0, right: 0}"
    }, {
      "name": "properties",
      "description": "With Text, Font and LayoutData containing `left`, `top` and `right` arguments.",
      "template": "{text: ${text}, font: \"14px\", layoutData: {left: 0, top: 0, right: 0}"
    }]
  };
  CodeMirror.templatesHint.addTemplates(templates);
})();

(function() {
  var templates = {
    "name": "javascript",
    "context": "javascript",
    "templates": [{
      "name": "properties",
      "description": "With LayoutData containing `left`, `top` and `right` arguments.",
      "template": "{layoutData: {left: 0, top: 0, right: 0}"
    }, {
      "name": "properties",
      "description": "With Text, Font and LayoutData containing `left`, `top` and `right` arguments.",
      "template": "{text: ${text}, font: \"14px\", layoutData: {left: 0, top: 0, right: 0}"
    }, {
      "name": "animationProperties",
      "description": "With the `opacity` property set for a fade out effect.",
      "template": "{opacity: 0}"
    }, {
      "name": "animationProperties",
      "description": "With the `translation` property set for a horizontal translation animation.",
      "template": "{transform: {translationX: 20}}"
    }]
  };
  CodeMirror.templatesHint.addTemplates(templates);
})();

Add CM templates for tabris.js animation props


const BPromise = require('bluebird');
const markers = require('../data/markers.json');
var util = require('../src/util/seeds');

exports.seed = function(knex, Promise) {
  return BPromise.map(markers, (marker, index) => {
    const row = {
      id: index + 1,
      type: marker.type,
      location: marker.location.longitude + ',' + marker.location.latitude,
      title: marker.title,
    };

    if (marker.url) {
      row.url = marker.url;
    }

    return util.insertOrUpdate(knex, 'markers', row);
  }, {concurrency: 1})
};

const BPromise = require('bluebird');
const markers = require('../data/markers.json');
var util = require('../src/util/seeds');

exports.seed = function(knex, Promise) {
  return BPromise.map(markers, (marker, index) => {
    const row = {
      id: index + 1,
      type: marker.type,
      location: marker.location.longitude + ',' + marker.location.latitude,
      title: marker.title,
      subtitle: marker.subtitle
    };

    if (marker.url) {
      row.url = marker.url;
    }

    return util.insertOrUpdate(knex, 'markers', row);
  }, {concurrency: 1})
};

Add subtitle field to marker seed


var path = require("path");

module.exports = function(bundle){
	if(bundle.source.map) {
		var filename = path.basename(removePlugin(bundleName(bundle))) + "." +
			bundle.buildType;
		bundle.source.code += wrap(filename, bundle.buildType);
	}
};

var pluginExp = /\..+!$/;
function removePlugin(name) {
	return name.replace(pluginExp, "");
}

function bundleName(bundle) {
	var name = bundle.name || bundle.bundles[0] || bundle.nodes[0].load.name;
	return name .replace("bundles/", "").replace(/\..+!/, "");
}

function wrap(filename, buildType) {
	switch(buildType) {
		case "css":
			return " /*# sourceMappingURL=" + filename + ".map */";
		default:
			return " //# sourceMappingURL=" + filename + ".map";
	}
}

var path = require("path");

module.exports = function(bundle){
	if(bundle.source.map) {
		var filename = path.basename(removePlugin(bundleName(bundle))) + "." +
			bundle.buildType;
		bundle.source.code += wrap(filename, bundle.buildType);
	}
};

var pluginExp = /\..+!$/;
function removePlugin(name) {
	return name.replace(pluginExp, "");
}

function bundleName(bundle) {
	var name = bundle.name || bundle.bundles[0] || bundle.nodes[0].load.name;
	return name .replace("bundles/", "").replace(/\..+!/, "");
}

function wrap(filename, buildType) {
	switch(buildType) {
		case "css":
			return "\n/*# sourceMappingURL=" + filename + ".map */";
		default:
			return "\n//# sourceMappingURL=" + filename + ".map";
	}
}

Put sourceMappingURL on a newline


histomicstk.App = girder.App.extend({

    initialize: function () {
        girder.fetchCurrentUser()
            .done(_.bind(function (user) {
                girder.eventStream = new girder.EventStream({
                    timeout: girder.sseTimeout || null
                });

                this.headerView = new histomicstk.views.Header({
                    parentView: this
                });

                this.bodyView = new histomicstk.views.Body({
                    parentView: this
                });

                if (user) {
                    girder.currentUser = new girder.models.UserModel(user);
                    girder.eventStream.open();
                }

                this.render();
            }, this));

        girder.events.on('g:loginUi', this.loginDialog, this);
        girder.events.on('g:registerUi', this.registerDialog, this);
        girder.events.on('g:resetPasswordUi', this.resetPasswordDialog, this);
        girder.events.on('g:alert', this.alert, this);
        girder.events.on('g:login', this.login, this);
    },
    render: function () {
        this.$el.html(histomicstk.templates.layout());

        this.headerView.setElement(this.$('#g-app-header-container')).render();
        this.bodyView.setElement(this.$('#g-app-body-container')).render();
        return this;
    }
});

histomicstk.App = girder.App.extend({

    initialize: function () {
        girder.fetchCurrentUser()
            .done(_.bind(function (user) {
                girder.eventStream = new girder.EventStream({
                    timeout: girder.sseTimeout || null
                });

                this.headerView = new histomicstk.views.Header({
                    parentView: this
                });

                this.bodyView = new histomicstk.views.Body({
                    parentView: this
                });

                if (user) {
                    girder.currentUser = new girder.models.UserModel(user);
                    girder.eventStream.open();
                }

                this.render();

                Backbone.history.start({pushState: false});
            }, this));

        girder.events.on('g:loginUi', this.loginDialog, this);
        girder.events.on('g:registerUi', this.registerDialog, this);
        girder.events.on('g:resetPasswordUi', this.resetPasswordDialog, this);
        girder.events.on('g:alert', this.alert, this);
        girder.events.on('g:login', this.login, this);
    },
    render: function () {
        this.$el.html(histomicstk.templates.layout());

        this.headerView.setElement(this.$('#g-app-header-container')).render();
        this.bodyView.setElement(this.$('#g-app-body-container')).render();
        return this;
    }
});

Use a router to navigate gui's


var express = require('express');
var router = express.Router();
var Watchlist = require('../models/watchlist');

// POST watchlist
router.post('/', function (req, res, next) {
  var user = req.user;
  var post = req.body;

  if (post.status == 'attend' || post.status == 'watch' ) {
    Watchlist.add(user, post, function (err, result) {
      if (err) throw err;
      if (!res.xhr) {
        res.redirect('/event/' + post.event_id);
      }
    });
  } else if (!post.status) {
    Watchlist.remove(user, post, function (err, result) {
      if (err) throw err;
      if (!res.xhr) {
        res.redirect('/event/' + post.event_id);
      }
    });
  }
});

// Get watchlist item status for event/user
router.get('/status/:event_id', function(req, res, next) {
  var user = req.user;
  Watchlist.get(user, req.params.event_id, function (err, result) {
    if (err) throw err;
    res.send(result);
  });
});

// GET watchlists by event
router.get('/list/:event_id', function(req, res, next) {
  Watchlist.getAllByEvent(req.params.event_id, function (err, watchlists) {
    if (err) throw err;
  });
});

module.exports = router;

var express = require('express');
var router = express.Router();
var Watchlist = require('../models/watchlist');

// POST watchlist
router.post('/', function (req, res, next) {
  var user = req.user;
  var post = req.body;

  if (post.status == 'attend' || post.status == 'watch' ) {
    Watchlist.add(user, post, function (err, result) {
      if (err) throw err;
      if (!req.xhr) {
        res.redirect('/event/' + post.event_id);
      }
    });
  } else if (!post.status) {
    Watchlist.remove(user, post, function (err, result) {
      if (err) throw err;
      if (!req.xhr) {
        res.redirect('/event/' + post.event_id);
      }
    });
  }
});

// Get watchlist item status for event/user
router.get('/status/:event_id', function(req, res, next) {
  var user = req.user;
  Watchlist.get(user, req.params.event_id, function (err, result) {
    if (err) throw err;
    res.send(result);
  });
});

// GET watchlists by event
router.get('/list/:event_id', function(req, res, next) {
  Watchlist.getAllByEvent(req.params.event_id, function (err, watchlists) {
    if (err) throw err;
  });
});

module.exports = router;

Fix typo causing unnecessary requests


var Arrow = require('arrow'),
	Collection = Arrow.Collection;

exports.query = function query(Model, options, next) {
	var self = this,
		collection = this.getCollection(Model);
	options = this.translateQueryKeys(Model, options);
	options = this.calculateQueryParams(options);

	collection.find(options.where, options.fields, {
		limit: options.limit,
		skip: options.skip,
		sort: options.order
	}, function (err, cursor) {
		/* istanbul ignore if */
		if (err) { return next(err); }
		var array = [];
		cursor.each(function (err, doc) {
			if (null === doc) {
				next(null, new Collection(Model, array));
			}
			else {
				array.push(self.createInstanceFromResult(Model, doc));
			}
		});
	});
};

var Arrow = require('arrow'),
	Collection = Arrow.Collection;

exports.query = function query(Model, options, next) {
	var self = this,
		collection = this.getCollection(Model);
	options = this.translateQueryKeys(Model, options);
	options = this.calculateQueryParams(options);

	if(typeof options.order === 'string') {
		options.order = options.order
			.split(',')
			.reduce(function(res, prop) {
				res[prop] = 1;
				return res;
			}, {});
	}

	collection.find(options.where, options.fields, {
		limit: options.limit,
		skip: options.skip,
		sort: options.order
	}, function (err, cursor) {
		/* istanbul ignore if */
		if (err) { return next(err); }
		var array = [];
		cursor.each(function (err, doc) {
			if (null === doc) {
				next(null, new Collection(Model, array));
			}
			else {
				array.push(self.createInstanceFromResult(Model, doc));
			}
		});
	});
};

Order by string prop option added