import buffer from '../buffer';

function websocket({ url, bufferTime = 0 }, { feed }) {
  const buf = buffer(feed, bufferTime);
  let socket;

  return {
    start: () => {
      socket = new WebSocket(url);
      socket.binaryType = 'arraybuffer';

      socket.onmessage = event => {
        if (typeof event.data === 'string') {
          buf.pushEvent(JSON.parse(event.data));
        } else {
          buf.pushText(String.fromCharCode.apply(null, new Uint8Array(event.data)));
        }
      }
    },

    stop: () => {
      socket.close();
    }
  }
}

export { websocket };

import buffer from '../buffer';

function websocket({ url, bufferTime = 0 }, { feed }) {
  const buf = buffer(feed, bufferTime);
  let socket;
  let reconnectDelay = 250;

  function connect() {
    socket = new WebSocket(url);
    socket.binaryType = 'arraybuffer';

    socket.onopen = () => {
      reconnectDelay = 250;
    }

    socket.onmessage = event => {
      if (typeof event.data === 'string') {
        buf.pushEvent(JSON.parse(event.data));
      } else {
        buf.pushText(String.fromCharCode.apply(null, new Uint8Array(event.data)));
      }
    }

    socket.onclose = event => {
      if (!event.wasClean) {
        console.debug(`reconnecting in ${reconnectDelay}...`);
        setTimeout(connect, reconnectDelay);
        reconnectDelay = Math.min(reconnectDelay * 2, 5000);
      }
    }
  }

  return {
    start: () => {
      connect();
    },

    stop: () => {
      if (socket !== undefined) {
        socket.close();
      }
    }
  }
}

export { websocket };

Implement reconnection with backoff for WebSocket driver


/* eslint-disable import/no-extraneous-dependencies */
require('dotenv').config();
const test = require('ava').test;
const pickpocket = require('../pickpocket');

const p = pickpocket({
  consumerKey: process.env.CONSUMER_KEY
});

test('output of getAuthorizationURL with valid request token',
  async t => p.obtainRequestToken().then((token) => {
    const url = p.getAuthorizationURL({ requestToken: token });
    t.truthy(url.startsWith('http'),
      'valid call to getAuthorizationURL returns a url');
  })
);

test('output of obtainAccessToken with unauthorized request token',
  async t => t.throws(
    p.obtainAccessToken({ requestToken: 'unauthorized_token' }),
    Error,
    'obtainAccessToken should throw a SyntaxError when called with an invalid request token'
  )
);

Test for invalid request token call


var compute = require('./hamming').compute;

describe('Hamming', function () {

  it('no difference between identical strands', function () {
    expect(compute('A', 'A')).toEqual(0);
  });

  xit('complete hamming distance for single nucleotide strand', function () {
    expect(compute('A','G')).toEqual(1);
  });

  xit('complete hamming distance for small strand', function () {
    expect(compute('AG','CT')).toEqual(2);
  });

  xit('small hamming distance', function () {
    expect(compute('AT','CT')).toEqual(1);
  });

  xit('small hamming distance in longer strand', function () {
    expect(compute('GGACG', 'GGTCG')).toEqual(1);
  });

  xit('ignores extra length on first strand when longer', function () {
    expect(compute('AAAG', 'AAA')).toEqual(0);
  });

  xit('ignores extra length on other strand when longer', function () {
    expect(compute('AAA', 'AAAG')).toEqual(0);
  });

  xit('large hamming distance', function () {
    expect(compute('GATACA', 'GCATAA')).toEqual(4);
  });

  xit('hamming distance in very long strand', function () {
    expect(compute('GGACGGATTCTG', 'AGGACGGATTCT')).toEqual(9);
  });

});

var compute = require('./hamming').compute;

describe('Hamming', function () {

  it('no difference between identical strands', function () {
    expect(compute('A', 'A')).toEqual(0);
  });

  xit('complete hamming distance for single nucleotide strand', function () {
    expect(compute('A','G')).toEqual(1);
  });

  xit('complete hamming distance for small strand', function () {
    expect(compute('AG','CT')).toEqual(2);
  });

  xit('small hamming distance', function () {
    expect(compute('AT','CT')).toEqual(1);
  });

  xit('small hamming distance in longer strand', function () {
    expect(compute('GGACG', 'GGTCG')).toEqual(1);
  });

  xit('no defined hamming distance for unequal string (first way)', function () {
    expect(compute('AAAG', 'AAA')).toBeUndefined();
  });

  xit('no defined hamming distance for unequal string (second way)', function () {
    expect(compute('AAA', 'AAAG')).toBeUndefined();
  });

  xit('large hamming distance', function () {
    expect(compute('GATACA', 'GCATAA')).toEqual(4);
  });

  xit('hamming distance in very long strand', function () {
    expect(compute('GGACGGATTCTG', 'AGGACGGATTCT')).toEqual(9);
  });

});

Fix tests with different length strings to look for undefined result, rather than zero.


redmineApp.controller('IssueShowController', function($scope, $rootScope, $window, $routeParams, $location, ProjectService, IssueService, Restangular) {
	$scope.issue = {};

	ProjectService.get($routeParams.project_id).then(function (project) {
		$rootScope.project = project;
	});

	IssueService.get($routeParams.id, 'attachments,changesets,children,journals,relations,watchers').then(function (issue) {
		originalIssue = Restangular.copy(issue);
		$scope.issue = issue;
	});

	$scope.deleteIssue = function (issue) {
		if ($window.confirm('Are you sure you wish to delete the issue?')) {
			IssueService.delete(issue.id).then(function () {
				$location.path('/projects/' + issue.project.identifier);
			});
		}
	};
});

redmineApp.controller('IssueShowController', function($scope, $rootScope, $window, $routeParams, $location, ProjectService, IssueService, Restangular) {
	$scope.issue = {};

	ProjectService.get($routeParams.project_id).then(function (project) {
		$rootScope.project = project;
	});

	IssueService.get($routeParams.id, 'attachments,changesets,children,journals,relations,watchers').then(function (issue) {
		originalIssue = Restangular.copy(issue);
		$scope.issue = issue;
	});

	$scope.deleteIssue = function (issue) {
		if ($window.confirm('Are you sure you wish to delete the issue?')) {
			IssueService.delete(issue.id).then(function () {
				$location.path('/projects/' + $rootScope.project.identifier + '/issues');
			});
		}
	};
});

Fix deleting an issue redirecting to an undefined project.


import deviceMiddleware from 'express-device';
import express from 'express';
import bodyParser from 'body-parser';
import winston from 'winston';

import routerRender from './middleware/routerRender';
import errorRender from './middleware/errorRender';
import staticMiddleware from './middleware/static';

const defaultConfig = {
  logLevel: process.env.NODE_LOGLEVEL || 'info',
  port: process.env.NODE_PORT || 3000,
};

export default function server(userConfig = {}) {
  const app = express();
  const config = { ...defaultConfig, ...userConfig };

  winston.level = config.logLevel;

  app.use('/static', staticMiddleware);

  if (process.env.NODE_ENV === 'production') {
    app.use('/assets', express.static('dist/frontend'));
  }

  app.use(deviceMiddleware.capture());
  app.use(bodyParser.json());
  app.use(bodyParser.json({ type: 'application/json' }));

  if (process.env.NODE_ENV !== 'production' && process.env.NODE_ENV !== 'test') {
    // eslint-disable-next-line global-require
    app.use(require('./middleware/dev').default);
  }

  app.use(routerRender);
  app.use(errorRender);

  app.ready = new Promise((resolve) => {
    app.server = app.listen(config.port, () => {
      winston.log('info', `Started server on port ${config.port}`);
      resolve();
    });
  });

  return app;
}

import deviceMiddleware from 'express-device';
import express from 'express';
import bodyParser from 'body-parser';
import winston from 'winston';

import routerRender from './middleware/routerRender';
import errorRender from './middleware/errorRender';
import staticMiddleware from './middleware/static';

const defaultConfig = {
  logLevel: process.env.NODE_LOG_LEVEL || 'info',
  port: process.env.NODE_PORT || 3000,
};

export default function server(userConfig = {}) {
  const app = express();
  const config = { ...defaultConfig, ...userConfig };

  winston.level = config.logLevel;

  app.use('/static', staticMiddleware);

  if (process.env.NODE_ENV === 'production') {
    app.use('/assets', express.static('dist/frontend'));
  }

  app.use(deviceMiddleware.capture());
  app.use(bodyParser.json());
  app.use(bodyParser.json({ type: 'application/json' }));

  if (process.env.NODE_ENV !== 'production' && process.env.NODE_ENV !== 'test') {
    // eslint-disable-next-line global-require
    app.use(require('./middleware/dev').default);
  }

  app.use(routerRender);
  app.use(errorRender);

  app.ready = new Promise((resolve) => {
    app.server = app.listen(config.port, () => {
      winston.log('info', `Started server on port ${config.port}`);
      resolve();
    });
  });

  return app;
}

Use nicer name for log level env variable


var lines = document.querySelectorAll('.diff-line-code');

for (var i = 0; i < lines.length; i++) {
  var line = lines[i],
      lineContent = line.innerText,
      firstChar = lineContent[0],
      restContent = lineContent.slice(1);

  var first = document.createElement('span');
  first.classList.add('clean-diff-sheker');
  first.setAttribute('data-char', firstChar);

  var rest = document.createElement('span');
  rest.innerText = restContent;

  line.innerText = '';
  line.appendChild(first);
  line.appendChild(rest);
}

var lines = document.querySelectorAll('.diff-line-code');

for (var i = 0; i < lines.length; i++) {
  var line = lines[i],
      commentButton = line.firstChild,
      lineContent = line.innerText,
      firstChar = lineContent[0],
      restContent = lineContent.slice(1);

  var first = document.createElement('span');
  first.classList.add('clean-diff-sheker');
  first.setAttribute('data-char', firstChar);

  var rest = document.createElement('span');
  rest.innerText = restContent;

  line.innerText = '';
  line.appendChild(commentButton);
  line.appendChild(first);
  line.appendChild(rest);
}

Fix comment button being removed


(function() {
  function selector(v) {
    return '[touch-action="' + v + '"]';
  }
  function rule(v) {
    return '{ -ms-touch-action: ' + v + '; touch-action: ' + v + '; }';
  }
  var attrib2css = [
    'none',
    'auto',
    'pan-x',
    'pan-y',
    {
      rule: 'pan-x pan-y',
      selectors: [
        'pan-x pan-y',
        'pan-y pan-x'
      ]
    }
  ];
  var styles = '';
  attrib2css.forEach(function(r) {
    if (String(r) === r) {
      styles += selector(r) + rule(r);
    } else {
      styles += r.selectors.map(selector) + rule(r.rule);
    }
  });
  var el = document.createElement('style');
  el.textContent = styles;
  // Use querySelector instead of document.head to ensure that in
  // ShadowDOM Polyfill that we have a wrapped head to append to.
  var h = document.querySelector('head');
  // document.write + document.head.appendChild = crazytown
  // use insertBefore instead for correctness in ShadowDOM Polyfill
  h.insertBefore(el, h.firstChild);
})();

(function() {
  function selector(v) {
    return '[touch-action="' + v + '"]';
  }
  function rule(v) {
    return '{ -ms-touch-action: ' + v + '; touch-action: ' + v + '; }';
  }
  var attrib2css = [
    'none',
    'auto',
    'pan-x',
    'pan-y',
    {
      rule: 'pan-x pan-y',
      selectors: [
        'pan-x pan-y',
        'pan-y pan-x'
      ]
    }
  ];
  var styles = '';
  attrib2css.forEach(function(r) {
    if (String(r) === r) {
      styles += selector(r) + rule(r);
    } else {
      styles += r.selectors.map(selector) + rule(r.rule);
    }
  });
  var el = document.createElement('style');
  el.textContent = styles;
  document.head.appendChild(el);
})();

Remove nasty querySelector / head / appendChild hack for ShadowDOM Polyfill


        // Copyright: 2013 PMSI-AlignAlytics
        // License: "https://github.com/PMSI-AlignAlytics/dimple/blob/master/MIT-LICENSE.txt"
        // Source: /src/objects/axis/methods/_parseDate.js
        this._parseDate = function (inDate) {
            // A javascript date object
            var outDate;
            if (this.dateParseFormat === null || this.dateParseFormat === undefined) {
                // If nothing has been explicity defined you are in the hands of the browser gods
                // may they smile upon you...
                outDate = Date.parse(inDate);
            } else {
                outDate = d3.time.format(this.dateParseFormat).parse(inDate);
            }
            // Return the date
            return outDate;
        };

        // Copyright: 2013 PMSI-AlignAlytics
        // License: "https://github.com/PMSI-AlignAlytics/dimple/blob/master/MIT-LICENSE.txt"
        // Source: /src/objects/axis/methods/_parseDate.js
        this._parseDate = function (inDate) {
            // A javascript date object
            var outDate;
            if (!isNaN(inDate)) {
                // If inDate is a number, assume it's epoch time
                outDate = new Date(inDate);
            } else if (this.dateParseFormat === null || this.dateParseFormat === undefined) {
                // If nothing has been explicity defined you are in the hands of the browser gods
                // may they smile upon you...
                outDate = Date.parse(inDate);
            } else {
                outDate = d3.time.format(this.dateParseFormat).parse(inDate);
            }
            // Return the date
            return outDate;
        };

Support time series data represented in epoch time


import Collapse from 'ember-bootstrap/components/base/bs-collapse';

export default Collapse.extend({
  classNameBindings: ['collapse', 'showContent:show', 'collapsing']
});

import Collapse from 'ember-bootstrap/components/base/bs-collapse';

export default Collapse.extend({
  classNameBindings: ['showContent:show']
});

Remove redundant class name bindings in BS4.


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

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

Fix manifest file wrong include name


;(function(){
  var app = angular.module('Communicant', []);

  app.controller('ListOfMessagesController', ['$scope', '$http', function($scope, $http){
    $http.get("/messages.json")
    .then(function(response){
      $scope.messages = response.data;
    })

  }]); // END ListOfMessagesController

  app.controller('SendMessageController', ['$scope', '$http', function($scope, $http){
    // console.log("Hello?");
    $scope.newMessage = { };
    $scope.submit = function(){
      $http.post("/messages.json", $scope.newMessage);
    };
    $http.get("/messages.json")
    .then(function(response){
      $scope.messages = response.data;
    })
  }]); // END SendMessageController

})(); // END IIFE

;(function(){
  var app = angular.module('Communicant', []);

  app.controller('ListOfMessagesController', ['$scope', '$http', function($scope, $http){
    $http.get("/messages.json")
    .then(function(response){
      $scope.messages = response.data;
    })

  }]); // END ListOfMessagesController

  app.controller('SendMessageController', ['$scope', '$http', function($scope, $http){
    // console.log("Hello?");
    $scope.newMessage = { };
    $scope.submit = function(){
      $http.post("/messages.json", $scope.newMessage);
    };

    $http.get("/messages.json")
    .then(function(response){
      $scope.messages = response.data;
    })
  }]); // END SendMessageController

// $timeout([fn], [2000], [invokeApply], [Pass]);

})(); // END IIFE

Add code commented note about setTimeout


$(function() {
	$(".add").button();
	$(".edit").button();
	$(".delete").button().click(function() {
		var res = confirm("Are you sure you want to delete this item?");
		if (res)
			window.location.href=$(this).attr('href');
		else
			return false;
	});
	$(".view").button();
	$(".submit").button();

	$("#ingredients_table table").tablesorter();
});

$(function() {
	$(".add").button();
	$(".edit").button();
	$(".delete").button().click(function() {
		var res = confirm("Are you sure you want to delete this item?");
		if (res)
			window.location.href=$(this).attr('href');
		else
			return false;
	});
	$(".view").button();
	$(".submit").button();

	$("#ingredients_table table").tablesorter();
	$("#effects_table table").tablesorter();
});

Add tablesorter to effects table


module.exports = function( config ) {
  config.set({
    // base path, that will be used to resolve files and exclude
    basePath: '',

    frameworks: ['mocha','requirejs'],

    // list of files / patterns to load in the browser
    files: [
      {pattern: 'test/lib/*.js', included: false},
      {pattern: 'app/bower_components/**/*.js', included: false},
      {pattern: 'app/scripts/**/*.js', included: false},
      {pattern: 'test/unit/**/*.test.js', included: false},
      // test main require module last
      'test/test-main.js'
    ],

    preprocessors: {
      'app/scripts/**/*.js': 'coverage'
    },

    autoWatch: true,

    // test results reporter to use
    // possible values: 'dots', 'progress', 'junit'
    reporters: ['progress','coverage'],

    // web server port
    port: 9876,

    // cli runner port
    runnerPort: 9100,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // 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: 60000,

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

module.exports = function( config ) {
  config.set({
    // base path, that will be used to resolve files and exclude
    basePath: '',

    frameworks: ['mocha','requirejs'],

    // list of files / patterns to load in the browser
    files: [
      {pattern: 'test/lib/*.js', included: false},
      {pattern: 'app/bower_components/**/*.js', included: false},
      {pattern: 'app/scripts/**/*.js', included: false},
      {pattern: 'test/unit/**/*.test.js', included: false},
      // test main require module last
      'test/test-main.js'
    ],

    preprocessors: {
      'app/scripts/**/*.js': 'coverage'
    },

    autoWatch: true,

    // test results reporter to use
    // possible values: 'dots', 'progress', 'junit'
    reporters: ['progress','coverage'],

    // web server port
    port: 9876,

    // cli runner port
    runnerPort: 9100,

    // enable / disable colors in the output (reporters and logs)
    colors: true,

    // Start these browsers, currently available:
    // - Chrome
    // - PhantomJS
    browsers: ['PhantomJS'],

    // If browser does not capture in given timeout [ms], kill it
    captureTimeout: 60000,

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

Update available browsers as this has changed by default in 0.10.2


module.exports = {
  CONFIG_FILE_NAME: 'ssh-seed.yml',
  PASS_FILE_NAME: 'ssh-seed.pass.yml',
  DEFAULT_CONFIG: {
    passphrase: {
      length: 12,
      options: '',
    },
    ssh_add: {
      'default': false,
      options: '',
    },
    ssh_keygen: {
      options: '',
    },
    keys: [],
  },
};

module.exports = {
  CONFIG_FILE_NAME: 'ssh-seed.yml',
  PASS_FILE_NAME: 'ssh-seed.pass.yml',
  DEFAULT_CONFIG: {
    passphrase: {},
    ssh_add: {
      'default': false,
      options: '',
    },
    ssh_keygen: {
      options: '',
    },
    keys: [],
  },
};

Change the default passphrase generation options


'use strict'

const path = require('path')

const projectRoot = path.join(__dirname, '..')
const appPackage = require(path.join(projectRoot, 'package.json'))

function getDistPath () {
  return path.join(projectRoot, 'dist', `${appPackage.productName}-${process.platform}-x64`)
}

function getProductName () {
  return appPackage.productName
}

function getCompanyName () {
  return appPackage.companyName
}

function getVersion () {
  return appPackage.version
}

function getOSXZipPath () {
  const productName = getProductName()
  return path.join(getDistPath(), '..', `${productName}.zip`)
}

function getWindowsInstallerPath () {
  const productName = getProductName()
  return path.join(getDistPath(), '..', 'installer', `${productName}.msi`)
}

module.exports = {getDistPath, getProductName, getCompanyName, getVersion, getOSXZipPath, getWindowsInstallerPath}

'use strict'

const path = require('path')

const projectRoot = path.join(__dirname, '..')
const appPackage = require(path.join(projectRoot, 'package.json'))

function getDistPath () {
  return path.join(projectRoot, 'dist', `${appPackage.productName}-${process.platform}-x64`)
}

function getProductName () {
  return appPackage.productName
}

function getCompanyName () {
  return appPackage.companyName
}

function getVersion () {
  return appPackage.version
}

function getOSXZipPath () {
  const productName = getProductName()
  return path.join(getDistPath(), '..', `${productName}.zip`)
}

function getWindowsInstallerPath () {
  const productName = getProductName()
  return path.join(getDistPath(), '..', 'installer', `${productName}Setup.msi`)
}

module.exports = {getDistPath, getProductName, getCompanyName, getVersion, getOSXZipPath, getWindowsInstallerPath}

Set Up The Bomb here too


const WebpackDevServer = require('webpack-dev-server');
const webpack = require('webpack');
const config = require('../webpack/webpack.config.dev');

new WebpackDevServer(webpack(config), {
  publicPath: config.output.publicPath,
  hot: true,
  stats: {
    colors: true,
  },
  historyApiFallback: {
    index: 'src/html/index.dev.html',
  },
}).listen(8080, '0.0.0.0', (err) => {
  if (err) {
    // eslint-disable-next-line no-console
    return console.log(err);
  }

  // eslint-disable-next-line no-console
  return console.log('Listening at http://localhost:8080/');
});

const WebpackDevServer = require('webpack-dev-server');
const webpack = require('webpack');
const config = require('../webpack/webpack.config.dev');

new WebpackDevServer(webpack(config), {
  publicPath: config.output.publicPath,
  hot: true,
  stats: 'errors-only',
  historyApiFallback: {
    index: 'src/html/index.dev.html',
  },
}).listen(8080, '0.0.0.0', (err) => {
  if (err) {
    // eslint-disable-next-line no-console
    return console.log(err);
  }

  // eslint-disable-next-line no-console
  return console.log('Listening at http://localhost:8080/');
});

Hide extra webpack stats on development.


describe('logge', function() {
  var $console, log;

  beforeEach(module('logge'));
  beforeEach(function() {
    var logMethod = function(msg) { log += (msg + ';'); };

    log = '';
    $console = {
      'debug': logMethod,
      'log': logMethod,
      'info': logMethod,
      'warn': logMethod,
      'error': logMethod
    };
  });

  describe('when console is present', function() {
    beforeEach(module(function($provide) {
      $provide.value('$window', {console: $console});
    }));

    it('logs messages', inject(function($logge) {
      $logge.debug('debug');
      $logge.log('log');
      $logge.info('info');
      $logge.warn('warn');
      $logge.error('error');
      expect(log).toEqual('debug;log;info;warn;error;');
    }));
  });

  describe('when console is not present', function() {
    beforeEach(module(function($provide) {
      $provide.value('$window', {});
    }));

    it('calls noop', inject(function($logge) {
      $logge.debug('debug;');
      $logge.log('log');
      $logge.info('info;');
      $logge.warn('warn;');
      $logge.error('error;');
      expect(log).toEqual('');
    }));
  });
});

describe('logge', function() {
  var $console, log;

  beforeEach(module('logge'));
  beforeEach(function() {
    var logMethod = function(msg) { log += (msg + ';'); };

    log = '';
    $console = {
      'debug': logMethod,
      'log': logMethod,
      'info': logMethod,
      'warn': logMethod,
      'error': logMethod
    };
  });

  describe('when console is present', function() {
    beforeEach(module(function($provide) {
      $provide.value('$window', {console: $console});
    }));

    it('logs messages', inject(function($logge) {
      $logge.debug('debug');
      $logge.log('log');
      $logge.info('info');
      $logge.warn('warn');
      $logge.error('error');
      expect(log).toEqual('debug;log;info;warn;error;');
    }));
  });

  describe('when console is not present', function() {
    beforeEach(module(function($provide) {
      $provide.value('$window', {});
    }));

    it('calls noop', inject(function($logge) {
      $logge.debug('debug;');
      $logge.log('log');
      $logge.info('info;');
      $logge.warn('warn;');
      $logge.error('error;');
      expect(log).toEqual('');
    }));
  });

  describe('when level is set', function() {
    beforeEach(module(function($provide, $loggeProvider) {
      $provide.value('$window', {console: $console});
      $loggeProvider.level('error');
    }));

    it('calls noop of equal or greater level', inject(function($logge) {
      $logge.info('info');
      $logge.error('error');
      expect(log).toEqual('error;');
    }));
  });
});

Add log level configuration specs


const path = require('path');
const sassTrue = require('sass-true')
const globImporter = require('node-sass-glob-importer')

const alreadyImported = []
const importOnce = (url, prev, done) => {
  const asAbsolute = path.isAbsolute(url) ? url : path.join(path.dirname(prev), url)
  const asAbsoluteDirname = path.dirname(asAbsolute)
  const asAbsoluteBaseStrip = path.basename(asAbsolute).replace(/^_/, '').replace(/.s[ca]ss$/, '')
  const isSameFile = (otherPath) => {
    const isSameDir = path.dirname(otherPath) === asAbsoluteDirname
    const otherPathBaseStrip = path.basename(otherPath).replace(/^_/, '').replace(/.s[ca]ss$/, '')
    const isCompatibleBase = otherPathBaseStrip === asAbsoluteBaseStrip
    return (isSameDir && isCompatibleBase)
  }
  if (alreadyImported.some(isSameFile)) {
    return {};
  } else {
    alreadyImported.push(asAbsolute)
    return null;
  }
}

const frameworkIncludesPath = path.join(__dirname, '../framework')
const sassFile = path.join(__dirname, 'test-framework.scss')

sassTrue.runSass({
  file: sassFile,
  importer: [globImporter(), importOnce],
  includePaths: [frameworkIncludesPath],
}, describe, it)

const path = require('path');
const sassTrue = require('sass-true')
const globImporter = require('node-sass-glob-importer')

const alreadyImported = []
const importOnce = (url, prev, done) => {
  const asAbsolute = path.isAbsolute(url) ? url : path.join(path.dirname(prev), url)
  const asAbsoluteDirname = path.dirname(asAbsolute)
  const asAbsoluteBaseStrip = path.basename(asAbsolute).replace(/^_/, '').replace(/.s[ca]ss$/, '')
  const isSameFile = (otherPath) => {
    const isSameDir = path.dirname(otherPath) === asAbsoluteDirname
    const otherPathBaseStrip = path.basename(otherPath).replace(/^_/, '').replace(/.s[ca]ss$/, '')
    const isCompatibleBase = otherPathBaseStrip === asAbsoluteBaseStrip
    return (isSameDir && isCompatibleBase)
  }
  if (alreadyImported.some(isSameFile)) {
    // console.log(`Not imported: ${asAbsolute}`)
    return {};
  } else {
    alreadyImported.push(asAbsolute)
    return null;
  }
}

const frameworkIncludesPath = path.join(__dirname, '../framework')
const sassFile = path.join(__dirname, 'test-framework.scss')

sassTrue.runSass({
  file: sassFile,
  importer: [globImporter(), importOnce],
  includePaths: [frameworkIncludesPath],
}, describe, it)

Add debug message for import once


require('coffee-script');
require('newrelic');
module.exports = require('./lib/social/main.coffee');

require('coffee-script');
module.exports = require('./lib/social/main.coffee');

Revert "add newrelic to social worker"


// js/services/note.js

(function() {
  "use strict";

  angular.module("NoteWrangler")
    .factory("Note", NoteFactory);

  NoteFactory.$inject = ["$http"];

  function NoteFactory($http) {
    function getAllNotes() {
      return $http({
        method: "GET",
        url: "/api/notes"
      });
    }

    function createNote(noteData) {
      return $http({
        method: "POST",
        url: "/api/notes",
        data: noteData
      })
    }

    return {
      getAllNotes,
      createNote
    }
  }
})();

// js/services/note.js

(function() {
  "use strict";

  angular.module("NoteWrangler")
    .factory("Note", NoteFactory);

  NoteFactory.$inject = ["$http", "$routeParams"];

  function NoteFactory($http, $routeParams) {
    function getAllNotes() {
      return $http({
        method: "GET",
        url: "/api/notes"
      });
    }

    function getNoteById() {
      return $http({
        method: "GET",
        url: "/api/notes/" + $routeParams.id
      })
    }

    function createNote(noteData) {
      return $http({
        method: "POST",
        url: "/api/notes",
        data: noteData
      })
    }

    return {
      getAllNotes,
      createNote,
      getNoteById
    }
  }
})();

Add getNoteById method. Add to


(function (root, factory) {
  if (typeof exports === 'object') {
    // CommonJS
    module.exports = factory();
  } else if (typeof define === 'function' && define.amd) {
    // AMD
    define([], function () {
      return (root.returnExportsGlobal = factory());
    });
  } else {
    // Global Variables

    var snabbtjs = factory();
    root.snabbtjs = snabbtjs;
    root.snabbt = snabbtjs.snabbt;
    //root.returnExportsGlobal = factory();
  }
}(this, function () {

(function (root, factory) {
  if (typeof exports === 'object') {
    // CommonJS
    module.exports = factory().snabbt;
  } else if (typeof define === 'function' && define.amd) {
    // AMD
    define([], function () {
      return (root.returnExportsGlobal = factory().snabbt);
    });
  } else {
    // Global Variables

    root.snabbt = factory().snabbt;
  }
}(this, function () {

Improve UMD boilerplate to export snabbt-function directly


import path from 'path';
import { logger } from '@storybook/node-logger';

import { getInterpretedFile } from './interpret-files';

function loadCustomAddons({ configDir }) {
  const storybookCustomAddonsPath = getInterpretedFile(path.resolve(configDir, 'addons'));

  if (storybookCustomAddonsPath) {
    logger.info('=> Loading custom addons config.');
    return [storybookCustomAddonsPath];
  }

  return [];
}

export default loadCustomAddons;

import path from 'path';
import { logger } from '@storybook/node-logger';

import { getInterpretedFile } from './interpret-files';

function loadCustomAddons({ configDir }) {
  const storybookCustomAddonsPath = getInterpretedFile(path.resolve(configDir, 'addons'));
  const storybookCustomManagerPath = getInterpretedFile(path.resolve(configDir, 'manager'));

  if (storybookCustomAddonsPath || storybookCustomManagerPath) {
    logger.info('=> Loading custom addons config.');
  }

  return [].concat(storybookCustomAddonsPath || []).concat(storybookCustomManagerPath || []);
}

export default loadCustomAddons;

ADD support for manager.js as a replacement for addons.js


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

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

    it('A new empty test', function() {
    });
});

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

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

    it('Just want to see placemark data type in the debugger', function() {
        var dataSource = new KmlDataSource();
        var url = 'http://localhost:8080/Apps/CesiumViewer/Gallery/KML_Samples.kml';

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

Add new test to allow me to visualize Placemark list in the debugger


var controller;
$(function(){
    var appName = "[ENTER YOUR APP NAME HERE]",
        app = $.ku4webApp.app();
    controller = $.ku4webApp.controllers[appName](app)
    $.ku4webApp.views[appName](app);

/*======================================================*/

 //[Other desired views or initialization scripting HERE]

/*======================================================*/

});

var controller;
$(function(){
    var appName = "[ENTER YOUR APP NAME HERE]",
        app = $.ku4webApp.app().throwErrors();
    controller = $.ku4webApp.controllers[appName](app)
    $.ku4webApp.views[appName](app);

/*======================================================*/

 //[Other desired views or initialization scripting HERE]

/*======================================================*/

});

Set app to throwErrors on by default


/**
* Equation.js
*
* @description :: An equation with input type, equation in source format,
* 				   and generated components.
* @docs        :: http://sailsjs.org/#!documentation/models
*/

module.exports = {

  attributes: {
  	mathType: {
    	type: 'string',
    	required: true,
    	enum: ['AsciiMath', 'MathML', 'LaTeX']
    },
    math: {
    	type: 'string',
    	required: true
    },
	equationName: 'string',
    qualityScore: 'integer',
	submittedBy: {
		model: 'user'
    },
    components: {
    	collection: 'component',
    	via: 'equation'
    },
    feedback: {
    	collection: 'feedback',
    	via: 'equation'
    }
  }
};

/**
* Equation.js
*
* @description :: An equation with input type, equation in source format,
* 				   and generated components.
* @docs        :: http://sailsjs.org/#!documentation/models
*/

module.exports = {

  attributes: {
  	mathType: {
    	type: 'string',
    	required: true,
    	enum: ['AsciiMath', 'MathML', 'TeX']
    },
    math: {
    	type: 'string',
    	required: true
    },
	equationName: 'string',
    qualityScore: 'integer',
	submittedBy: {
		model: 'user'
    },
    components: {
    	collection: 'component',
    	via: 'equation'
    },
    feedback: {
    	collection: 'feedback',
    	via: 'equation'
    }
  }
};

Fix mathtype enum for latex


describe("Dom Tests", function() {

    var substrata = {};

    beforeEach(function(){
        substrata = new Substrata();
    });

    it("has a function called testRun which returns true", function() {
        expect(true).to.be.true;
    });

    it("has a function called setupWindow which returns an integer", function() {
        expect(true).to.be.true;
    })

});

describe("Dom Tests", function() {

    var substrata = {};

    beforeEach(function(){
        substrata = new Substrata();
    });

    it("has a function called testRun which returns true", function() {
        expect(substrata.testRun()).to.be.true;
    });

    it("has a function called setupWindow which returns an integer", function() {
        expect(substrata.setupWindow()).to.be.a('number');
    })

});

Use the object to test


'use strict'

/* global browser */

const cmds = require('wdio-screen-commands')

module.exports = {
  before: () => {
    global.should = require('chai').should()
    browser.addCommand('saveScreenshotByName', cmds.saveScreenshotByName)
    browser.addCommand('saveAndDiffScreenshot', cmds.saveAndDiffScreenshot)
    if (browser.config.maximizeWindow) browser.maximizeWindow()
  },
  beforeTest: test => {
    cmds.startScreenRecording(test)
  },
  afterTest: async test => {
    await cmds.stopScreenRecording(test)
    cmds.saveScreenshotByTest(test)
  }
}

'use strict'

/* global browser, Promise */

const cmds = require('wdio-screen-commands')

/* eslint-disable jsdoc/valid-types */
/** @type WebdriverIO.Config */
const config = {
  before: async () => {
    global.Should = require('chai').should()
    browser.addCommand('saveScreenshotByName', cmds.saveScreenshotByName)
    browser.addCommand('saveAndDiffScreenshot', cmds.saveAndDiffScreenshot)
    if (browser.config.maximizeWindow) await browser.maximizeWindow()
  },
  beforeTest: async test => {
    await cmds.startScreenRecording(test)
  },
  afterTest: async test => {
    await Promise.all([
      cmds.stopScreenRecording(test),
      cmds.saveScreenshotByTest(test)
    ])
  }
}

module.exports = config

Update hooks for latest wdio-screen-commands.


class MetaData {
  constructor(data, extra_key) {
    this.data = data;
    this.extra_key = extra_key;
  }

  get(keys) {
    if (!this.data)
      return [];

    if (this.extra_key)
      return this.slice_with_extra_key(keys);
    else
      return this.slice_without_extra_key(keys);
  }

  slice_with_extra_key(keys) {
    const data = [];

    keys.forEach((k) => {
      if (this.data[k] && this.data[k][this.extra_key])
        data.push({class: k, value: this.data[k][this.extra_key]});
    });

    return data;
  }

  slice_without_extra_key(keys) {
    const data = [];

    keys.forEach((k) => {
      if (this.data[k])
        data.push({class: k, value: this.data[k]});
    });

    return data;
  }
}

module.exports = MetaData;

class MetaData {
  constructor(data, extra_key) {
    this.data = data;
    this.extra_key = extra_key;
  }

  get(keys) {
    return this.slice(keys).filter((k, i) => typeof k.value === 'string');
  }

  slice(keys) {
    if (!this.data)
      return [];

    if (this.extra_key)
      return this.slice_with_extra_key(keys);
    else
      return this.slice_without_extra_key(keys);
  }

  slice_with_extra_key(keys) {
    const data = [];

    keys.forEach((k) => {
      if (this.data[k] && this.data[k][this.extra_key])
        data.push({class: k, value: this.data[k][this.extra_key]});
    });

    return data;
  }

  slice_without_extra_key(keys) {
    const data = [];

    keys.forEach((k) => {
      if (this.data[k])
        data.push({class: k, value: this.data[k]});
    });

    return data;
  }
}

module.exports = MetaData;

Return metadata which are in {"class": string, "value": string} format only


import React, { Component } from 'react';
import { connect } from 'react-redux';

class Home extends Component {
  render () {
    return (
      <div>
        Wellcome to auction-app! ;)
      </div>
    );
  }
}

export default connect(() => {
  return { };
})(Home);

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

import Buyer from '../components/buyer';

class Home extends Component {
  static propTypes = {
    history: PropTypes.object.isRequired,
  };

  handleBuyerClick (id) {
    this.props.history.push(`/auctions/${id}`);
  }

  render () {
    const buyersList = [
      { id: 1, name: 'Buyer 1' },
      { id: 2, name: 'Buyer 2' },
    ];

    const buyers = buyersList
      .map((buyer) => {
        return (
          <Buyer
            key={buyer.id}
            buyer={buyer}
            onClick={::this.handleBuyerClick}
          />
        );
      });

    return (
      <div>
        Choose your Buyer:
        {buyers}
      </div>
    );
  }
}

export default connect(() => {
  return { };
})(Home);

Add buyers to Home container


'use strict';

import models      from '../../models';
import { GENERIC } from '../../utils/errorTypes.js';

let User = models.User;

export default function resolveUser(req, res, next)  {
    let jwtUserId = req.user.id;

    User.findById(jwtUserId)
        .then(function (loggedInUser) {
            if (!loggedInUser) {
                res.err(404, 'User not found!')
            } else {
                req.user = loggedInUser;
                return next();
            }
        })
        .catch(function (err) {
            res.err(500)
        })
};

'use strict';

import models      from '../../models';
import { GENERIC } from '../../utils/errorTypes.js';

let User = models.User;

export default function resolveUser(req, res, next)  {
    let jwtUserId = req.user.id;

    User.findById(jwtUserId)
        .then(function (loggedInUser) {
            if (!loggedInUser) {
                res.err(404, 'User not found!')
            } else {
                req.user = loggedInUser;
                next();
                return null;
            }
        })
        .catch(function (err) {
            res.err(500)
        })
};

Return null from resolveuser since it seems to confuse bluebird


'use strict';

const graphql = require('graphql');

const MoistureType = new graphql.GraphQLObjectType({
  name: 'Moisture',
  fields: {
    date: { type: graphql.GraphQLString },
    moisture: { type: graphql.GraphQLFloat },
  }
});

module.exports = function(dayService) {
  return {
    name: 'DayQuery',
    description: 'Retrieve moisture levels per day',
    type: new graphql.GraphQLList(MoistureType),
    args: {
      hours: {
        type: graphql.GraphQLInt,
        defaultValue: 1
      },
    },
    resolve: (_, args, ast) => {
      const hours = args.hours > 0 ? args.hours : 1;
      return dayService.getLastHours('garden-aid-client-test-js', hours);
    }
  }
}

'use strict';

const graphql = require('graphql');

const MoistureType = new graphql.GraphQLObjectType({
  name: 'Moisture',
  fields: {
    date: { type: graphql.GraphQLString },
    moisture: { type: graphql.GraphQLFloat },
  }
});

module.exports = function(dayService) {
  return {
    name: 'DayQuery',
    description: 'Retrieve moisture levels per day',
    type: new graphql.GraphQLList(MoistureType),
    args: {
      hours: {
        type: graphql.GraphQLInt,
        defaultValue: 1
      },
    },
    resolve: (_, args, ast) => {
      const hours = args.hours > 0 ? args.hours : 1;
      // TODO remove clientid
      return dayService.getLastHours('garden-aid-client-test-js', hours);
    }
  }
}

Add comment about client id


import { split } from './int-util.js'
import { name, clear, singularize, addConjunction, addComma, write } from './parts-util.js'

/**
 * Escrever números maiores que mil.
 *
 * @param {string} int Um número inteiro maior que mil.
 * @returns {number} Retorna o valor por extenso.
 */
const gt1000 = (int) => {
  let number = write(addComma(addConjunction(singularize(clear(name(split(int)))), int)))

  return number.join(' ')
}

export default gt1000

import { split } from './int-util'
import { name, clear, singularize, addConjunction, addComma, write } from './parts-util'

/**
 * Escrever números maiores que mil.
 *
 * @param {string} int Um número inteiro maior que mil.
 * @returns {number} Retorna o valor por extenso.
 */
const gt1000 = (int) => {
  let number = write(addComma(addConjunction(singularize(clear(name(split(int)))), int)))

  return number.join(' ')
}

export default gt1000

Remove extensão .js de alguns imports


/**
 * @class Admin_Form_Song
 * @extends CM_Form_Abstract
 */
var Admin_Form_Song = CM_Form_Abstract.extend({
	_class: 'Admin_Form_Song'
});

/**
 * @class Admin_Form_Song
 * @extends CM_Form_Abstract
 */
var Admin_Form_Song = CM_Form_Abstract.extend({
	_class: 'Admin_Form_Song',

	childrenEvents: {
		'Denkmal_FormField_FileSong uploadComplete': function(field, files) {
			this._setLabelFromFilename(files[0].name);
		}
	},

	/**
	 * @param {String} filename
	 */
	_setLabelFromFilename: function(filename) {
		filename = filename.replace(/\.[^\.]+$/, '');
		this.getField('label').setValue(filename);
	}
});

Set default label on song upload from filename


import EditorControllerMixin from 'ghost/mixins/editor-base-controller';

var EditorNewController = Ember.ObjectController.extend(EditorControllerMixin, {
    actions: {
        /**
          * Redirect to editor after the first save
          */
        save: function () {
            var self = this;
            this._super().then(function (model) {
                if (model.get('id')) {
                    self.transitionTo('editor.edit', model);
                }
                return model;
            });
        }
    }
});

export default EditorNewController;

import EditorControllerMixin from 'ghost/mixins/editor-base-controller';

var EditorNewController = Ember.ObjectController.extend(EditorControllerMixin, {
    actions: {
        /**
          * Redirect to editor after the first save
          */
        save: function () {
            var self = this;
            this._super().then(function (model) {
                if (model.get('id')) {
                    self.transitionToRoute('editor.edit', model);
                }
                return model;
            });
        }
    }
});

export default EditorNewController;

Fix warning about transitionTo being deprecated


define([
    'backbone',
    'modules/boilerplate/module',
    'modules/boilerplate/views/home',
], function (Backbone, BoilerplateModule, HomeView) {

    var Router = Backbone.SubRoute.extend({

        routes: {
            "": "home",
        },

        home: function() {
            // var homeView = new HomeView();
            // var renderedView = homeView.render();
            // renderedView.$el.appendTo("body");
        }

    });

    return Router;

});

define([
    'backbone',
    'modules/boilerplate/module',
    'modules/boilerplate/views/home',
], function (Backbone, BoilerplateModule, HomeView) {

    var Router = Backbone.SubRoute.extend({

        routes: {
            "": "home",
            "*404": "404" // catch-all route
        },

        home: function() {
            // var homeView = new HomeView();
            // var renderedView = homeView.render();
            // renderedView.$el.appendTo("body");
        },

        "404": function() {
            console.error("Route 404");
        }

    });

    return Router;

});

Add 404 catch all route to boilerplate module code


/**
 * util-lang.js - The minimal language enhancement
 */

function isType(type) {
  return function(obj) {
    return Object.prototype.toString.call(obj) === "[object " + type + "]"
  }
}

var isObject = isType("Object")
var isString = isType("String")
var isArray = Array.isArray || isType("Array")
var isFunction = isType("Function")

var _cid = 0
function cid() {
  return _cid++
}

/**
 * util-lang.js - The minimal language enhancement
 */

function isType(type) {
  return function(obj) {
    return {}.toString.call(obj) == "[object " + type + "]"
  }
}

var isObject = isType("Object")
var isString = isType("String")
var isArray = Array.isArray || isType("Array")
var isFunction = isType("Function")

var _cid = 0
function cid() {
  return _cid++
}

Improve isType function for reducing gzip size


module.exports = {
  normalizeEntityName: function() {
    // this prevents an error when the entityName is
    // not specified (since that doesn't actually matter
    // to us
  },

  afterInstall: function() {
    return this.addBowerPackagesToProject([
      { name: 'qunit',                           target: '~1.17.1' },
      { name: 'ember-cli/ember-cli-test-loader', target: '0.1.3'   },
      { name: 'ember-qunit-notifications',       target: '0.0.7'   },
      { name: 'ember-qunit',                     target: '0.4.9'   }
    ]);
  }
};

module.exports = {
  normalizeEntityName: function() {
    // this prevents an error when the entityName is
    // not specified (since that doesn't actually matter
    // to us
  },

  afterInstall: function() {
    return this.addBowerPackagesToProject([
      { name: 'qunit',                           target: '~1.18.0' },
      { name: 'ember-cli/ember-cli-test-loader', target: '0.1.3'   },
      { name: 'ember-qunit-notifications',       target: '0.0.7'   },
      { name: 'ember-qunit',                     target: '0.4.9'   }
    ]);
  }
};

Update QUnit version to 1.18.0.


process.traceDeprecation = true;
const path = require("path");
const patternslib_config = require("@patternslib/patternslib/webpack/webpack.config");
const svelte_config = require("@patternslib/pat-content-browser/webpack.svelte");

module.exports = async (env, argv, build_dirname = __dirname) => {
    let config = {
        entry: {
            "bundle.min": path.resolve(__dirname, "src/index.js"),
        },
    };

    config = svelte_config(env, argv, patternslib_config(env, argv, config, ["mockup"]));
    config.output.path = path.resolve(__dirname, "dist/");

    if (process.env.NODE_ENV === "development") {
        // Note: ``publicPath`` is set to "auto" in Patternslib,
        //        so for the devServer the public path set to "/".
        config.devServer.port = "8000";
        config.devServer.static.directory = path.resolve(__dirname, "./docs/_site/");
    }

    if (env && env.DEPLOYMENT === "plone") {
        config.output.path = path.resolve(
            build_dirname,
            "../plone.staticresources/src/plone/staticresources/static/bundle-plone/"
        );
    }

    return config;
};

process.traceDeprecation = true;
const path = require("path");
const patternslib_config = require("@patternslib/patternslib/webpack/webpack.config");
const svelte_config = require("@patternslib/pat-content-browser/webpack.svelte");

module.exports = async (env, argv, build_dirname = __dirname) => {
    let config = {
        entry: {
            "bundle.min": path.resolve(__dirname, "src/index.js"),
        },
        externals: {
            window: "window",
            $: 'jquery',
            jquery: 'jQuery',
            "window.jquery": 'jQuery',
        },
    };

    config = svelte_config(env, argv, patternslib_config(env, argv, config, ["mockup"]));
    config.output.path = path.resolve(__dirname, "dist/");

    if (process.env.NODE_ENV === "development") {
        // Note: ``publicPath`` is set to "auto" in Patternslib,
        //        so for the devServer the public path set to "/".
        config.devServer.port = "8000";
        config.devServer.static.directory = path.resolve(__dirname, "./docs/_site/");
    }

    if (env && env.DEPLOYMENT === "plone") {
        config.output.path = path.resolve(
            build_dirname,
            "../plone.staticresources/src/plone/staticresources/static/bundle-plone/"
        );
    }

    return config;
};

Add jquery as an external


'use strict';

/*@ngInject*/
module.exports = function($state) {
  if ($state.params.student) {
  }
  console.log(Porthole);
};

/*global Porthole*/
'use strict';

/*@ngInject*/
module.exports = function($state) {
  var windowProxy = new Porthole.WindowProxy();
  var postObj = {
    action: 'activity_complete',
  };

  if ($state.params.student) {
    postObj.id = $state.params.student;
  }

  windowProxy.post(postObj);

};

Send a message through porthole


var React = require('react');
var urllite = require('urllite');
var renderDocumentString = require('../utils/renderDocumentString');

var connectMiddleware = function(router) {
  return function(req, res, next) {
    // Get the part of the URL we care about.
    // TODO: Allow this to be mounted at a different base and strip that from pathname
    var parsed = urllite(req.url);
    var url = parsed.pathname + parsed.search + parsed.hash;

    var rres = router.dispatch(url, {initialOnly: true});
    rres.request
      .on('error', function(err) {
        // The React router doesn't want to handle it. That's okay, let
        // something else.
        if (err.name === 'Unhandled') return next();

        // Uh oh. A real error.
        return next(err);
      })
      .on('end', function() {
        var contentType = rres.contentType(); // Guess from contentType if not present

        res.statusCode = rres._notFound ? 404 : 200;
        res.setHeader('Content-Type', contentType);
        res.end(renderDocumentString(rres));
      });
  };
};

module.exports = connectMiddleware;

var React = require('react');
var urllite = require('urllite');
var renderDocumentString = require('../utils/renderDocumentString');

var connectMiddleware = function(router) {
  return function(req, res, next) {
    // Get the part of the URL we care about.
    // TODO: Allow this to be mounted at a different base and strip that from pathname
    var parsed = urllite(req.url);
    var url = parsed.pathname + parsed.search + parsed.hash;

    router.dispatch(url, {initialOnly: true}, function(err, rres) {
      if (err) {
        // The React router doesn't want to handle it. That's okay, let
        // something else.
        if (err.name === 'Unhandled') return next();

        // Uh oh. A real error.
        return next(err);
      }

      var contentType = rres.contentType(); // Guess from contentType if not present

      res.statusCode = rres._notFound ? 404 : 200;
      res.setHeader('Content-Type', contentType);
      res.end(renderDocumentString(rres));
    });
  };
};

module.exports = connectMiddleware;

Use dispatch callback in connect middleware


var jss = require('jss');
var extend = require('jss-extend');
var nested = require('jss-nested');
var camelCase = require('jss-camel-case');
var defaultUnit = require('jss-default-unit');

var perdido = require('perdido');

jss.use(extend());
jss.use(nested());
jss.use(camelCase());
jss.use(defaultUnit());

var testGrid = {
  article: {
    extend: perdido.flexContainer('row'),
    '& div': {
      extend: perdido.column('1/3'),
    },
  },
};

var styleSheet = jss.createStyleSheet(testGrid, {named: false});

styleSheet.toString();

perdido = perdido.create('30px', true);
perdido.flex = true;

var testGrid2 = {
  article: {
    extend: perdido.flexContainer('row'),
    '& div': {
      extend: perdido.column('1/3'),
    },
  },
};

var styleSheet2 = jss.createStyleSheet(testGrid2, {named: false});

styleSheet2.toString();

var jss = require('jss');
var extend = require('jss-extend');
var nested = require('jss-nested');
var camelCase = require('jss-camel-case');
var defaultUnit = require('jss-default-unit');

var perdido = require('perdido');

jss.use(extend());
jss.use(nested());
jss.use(camelCase());
jss.use(defaultUnit());

var testGrid = {
  article: {
    extend: perdido.flexContainer('row'),
    '& div': {
      extend: perdido.column('1/3'),
    },
  },
};

var styleSheet = jss.createStyleSheet(testGrid, {named: false});

styleSheet.toString();

var perdidoFlex = perdido.create('30px', {flex: true});
perdido.flex = true;

var testGrid2 = {
  article: {
    extend: perdidoFlex.flexContainer('row'),
    '& div': {
      extend: perdidoFlex.column('1/3'),
    },
  },
};

var styleSheet2 = jss.createStyleSheet(testGrid2, {named: false});

styleSheet2.toString();

Update tonic example for new API


import { Geometry } from './three.js';
import { validatePropString } from './utils.js';
import { geometries } from './object-stores.js';

export default {
  inject: ['vglGeometries'],
  props: {
    name: validatePropString,
  },
  computed: {
    inst: () => new Geometry(),
  },
  watch: {
    inst: {
      handler(inst, oldInst) {
        if (oldInst) delete geometries[oldInst.uuid];
        geometries[inst.uuid] = inst;
        this.$set(this.vglGeometries.forSet, this.name, inst.uuid);
      },
      immediate: true,
    },
    name(name, oldName) {
      if (this.vglGeometries.forGet[oldName] === this.inst.uuid) this.$delete(this.vglGeometries.forSet, oldName);
      this.$set(this.vglGeometries.forSet, name, this.inst.uuid);
    },
  },
  beforeDestroy() {
    delete geometries[this.inst.uuid];
    if (this.vglGeometries.forGet[this.name] === this.inst.uuid) this.$delete(this.vglGeometries.forSet, this.name);
  },
  render(h) {
    return this.$slots.default ? h('div', this.$slots.default) : undefined;
  }
};

import { BufferGeometry } from './three.js';
import { validatePropString } from './utils.js';
import { geometries } from './object-stores.js';

export default {
  inject: ['vglGeometries'],
  props: {
    name: validatePropString,
  },
  computed: {
    inst: () => new BufferGeometry(),
  },
  watch: {
    inst: {
      handler(inst, oldInst) {
        if (oldInst) delete geometries[oldInst.uuid];
        geometries[inst.uuid] = inst;
        this.$set(this.vglGeometries.forSet, this.name, inst.uuid);
      },
      immediate: true,
    },
    name(name, oldName) {
      if (this.vglGeometries.forGet[oldName] === this.inst.uuid) {
        this.$delete(this.vglGeometries.forSet, oldName);
      }
      this.$set(this.vglGeometries.forSet, name, this.inst.uuid);
    },
  },
  beforeDestroy() {
    delete geometries[this.inst.uuid];
    if (this.vglGeometries.forGet[this.name] === this.inst.uuid) {
      this.$delete(this.vglGeometries.forSet, this.name);
    }
  },
  render(h) {
    return this.$slots.default ? h('div', this.$slots.default) : undefined;
  },
};

Use the BufferGeometry class instead of the Geometry.


Ember.Validations.Errors = Ember.Object.extend({
  add: function(property, value) {
    this.set(property, (this.get(property) || []).concat(value));
  },
  clear: function() {
    var keys = Object.keys(this);
    for(var i = 0; i < keys.length; i++) {
      delete this[keys[i]];
    }
  }
});

Ember.Validations.Errors = Ember.Object.extend({
  add: function(property, value) {
    this.set(property, (this.get(property) || []).concat(value));
  },
  clear: function() {
    var keys = Object.keys(this);
    for(var i = 0; i < keys.length; i++) {
      this.set(keys[i], undefined);
      delete this[keys[i]];
    }
  }
});

Set to undefined when clearing


({
  mainConfigFile: './require.conf.js',
  dir: '../dist',
  modules: [
    {
      name: 'app',
      exclude: [
        /*
         * https://groups.google.com/forum/#!msg/requirejs/jiaDogbA1EQ/jKrHL0gs21UJ
         * text plugin is evaluated by r.js
         * required for building but useless into build
         */
        'text'
      ]
    }
  ],
  optimize: 'none',
  useStrict: true,
  paths: {
    'angular': 'empty:'
  }
  /*
   * DO NOT USE STUBMODULES OPTION EXCEPTED FOR APPCACHE BUILDS.
   * stubModules: ['text']
   */
})

({
  mainConfigFile: './require.conf.js',
  out: '../dist/app.js',
  exclude: [
    /*
     * https://groups.google.com/forum/#!msg/requirejs/jiaDogbA1EQ/jKrHL0gs21UJ
     * text plugin is evaluated by r.js
     * required for building but useless into build
     */
    'text'
  ],
  optimize: 'none',
  useStrict: true,
  paths: {
    'angular': 'empty:'
  }
  /*
   * DO NOT USE STUBMODULES OPTION EXCEPTED FOR APPCACHE BUILDS.
   * stubModules: ['text']
   */
})

Build into single file rather than by module


import { createServer } from 'http'
import { Plugin } from 'munar-core'
import micro, { createError } from 'micro'

export default class Serve extends Plugin {
  static defaultOptions = {
    port: 3000
  }

  enable () {
    this.server = micro(this.onRequest)

    this.server.listen(this.options.port)
  }

  disable () {
    this.server.close()
  }

  onRequest = async (req, res) => {
    const pluginName = req.url.split('/')[1]
    const plugin = await this.bot.getPlugin(pluginName)

    if (!plugin || typeof plugin.serve !== 'function') {
      throw createError(404, 'That plugin does not exist or does not expose a web interface.')
    }

    return plugin.serve(req, res, {
      send: micro.send,
      sendError: micro.sendError,
      createError: micro.createError,
      json: micro.json
    })
  }
}

import { createServer } from 'http'
import { Plugin } from 'munar-core'
import micro, { createError } from 'micro'

export default class Serve extends Plugin {
  static defaultOptions = {
    port: 3000
  }

  enable () {
    this.server = micro(this.onRequest)

    this.server.listen(this.options.port)
  }

  disable () {
    this.server.close()
  }

  onRequest = async (req, res) => {
    const pluginName = req.url.split('/')[1]
    const plugin = await this.bot.getPlugin(pluginName)

    if (!plugin || typeof plugin.serve !== 'function') {
      throw createError(404, 'That plugin does not exist or does not expose a web interface.')
    }

    // Remove plugin name from the URL.
    const parts = req.url.split('/')
    parts.splice(1, 1)
    req.url = parts.join('/')

    return plugin.serve(req, res, {
      send: micro.send,
      sendError: micro.sendError,
      createError: micro.createError,
      json: micro.json
    })
  }
}

Remove plugin name from URL before passing it to the plugin.


/*
 * ReadmePage
 *
 * This is the page users see when they click the "Setup" button on the HomePage
 */

import React, { Component} from 'react';
import { Link } from 'react-router';

export default class AboutPage extends Component {
  render() {
    return (

Further Setup

Assuming you have already cloned the repo and ran all the commands from the README (otherwise you would not be here), these are the further steps:

Replace my name and the package name in the package.json file

Replace the two components with your first component

Replace the default actions with your first action

Delete css/components/_home.css and add the styling for your component

And finally, update the unit tests

        <Link className="btn" to="/">Home</Link>

    );
  }
}

/*
 * ReadmePage
 *
 * This is the page users see when they click the "Setup" button on the HomePage
 */

import React, { Component } from 'react';
import { Link } from 'react-router';

export default class AboutPage extends Component {
  render() {
    return (

Further Setup

Assuming you have already cloned the repo and ran all the commands from the README (otherwise you would not be here), these are the further steps:

Replace my name and the package name in the package.json file

Replace the two components with your first component

Replace the default actions with your first action

Delete css/components/_home.css and add the styling for your component

And finally, update the unit tests

        <Link className="btn" to="/">Home</Link>

    );
  }
}

Fix spacing on import in ReadmePage.


var async = require('async')
var rb = require('./rubygems')

exports.run = (root, step, done) => {
  var gems = {}
  var error = false

  getGem({name: root}, (err) => {
    if (err) {
      done(err)
      return
    }
    done(null, gems)
  })

  function getGem (gem, done) {
    if (error) {
      done(error)
      return
    }

    // skip
    if (gems[gem.name]) {
      done(error)
      return
    }

    gems[gem.name] = true

    // get
    rb.get('gems/' + gem.name, (err, res) => {
      if (err) {
        done(err)
        return
      }

      gems[gem.name] = res.body

      if (step) {
        error = step(res.body)
      }
      // client has disconnected
      if (error) {
        done(error)
        return
      }

      // deps
      if (res.body.dependencies.runtime.length) {
        deps(res.body.dependencies.runtime, done)
      }
      // bottom
      else {
        done()
      }
    })
  }

  function deps (dependencies, done) {
    async.each(dependencies, getGem, done)
  }
}

var https = require('https')
var async = require('async')
var rb = require('./rubygems')

exports.run = (root, step, done) => {
  var gems = {}
  var error = false
  var agent = new https.Agent({keepAlive: true, maxSockets: 3})

  getGem({name: root}, (err) => {
    agent.destroy()
    if (err) {
      done(err)
      return
    }
    done(null, gems)
  })

  function getGem (gem, done) {
    if (error) {
      done(error)
      return
    }

    // skip
    if (gems[gem.name]) {
      done(error)
      return
    }

    gems[gem.name] = true

    // get
    rb.get('gems/' + gem.name, {agent}, (err, res) => {
      if (err) {
        done(err)
        return
      }

      gems[gem.name] = res.body

      if (step) {
        error = step(res.body)
      }
      // client has disconnected
      if (error) {
        done(error)
        return
      }

      // deps
      if (res.body.dependencies.runtime.length) {
        deps(res.body.dependencies.runtime, done)
      }
      // bottom
      else {
        done()
      }
    })
  }

  function deps (dependencies, done) {
    async.each(dependencies, getGem, done)
  }
}

Use 3 persistent tcp connections while discovering the deps graph


'use strict';

var PIXI = window.PIXI,
    Point = require('../data/point'),
    Rect = require('../data/rect');

function Frame(position, url, options) {
  this.pos = position;
  this.dir = options.direction || new Point(1, 1);
  this.offset = options.offset || new Point(0, 0);

  var base = PIXI.BaseTexture.fromImage(url, false, PIXI.scaleModes.NEAREST),
      slice = options.crop || new Rect(0, 0, base.width, base.height),
      tex = new PIXI.Texture(base, slice);

  this.sprite = new PIXI.Sprite(tex);

  this.render();
}

Frame.prototype.render = function() {
  var gPos = this.sprite.position,
      gScale = this.sprite.scale;

  gPos.x = Math.round(this.pos.x + this.offset.x);
  gPos.y = Math.round(this.pos.y + this.offset.y);

  gScale.x = this.dir.x;
  gScale.y = this.dir.y;

  /*
   * Flipping will result in the sprite appearing to jump (flips on the 0,
   * rather than mid-sprite), so subtract the sprite's size from its position
   * if it's flipped.
   */

  if(gScale.x < 0) gPos.x -= this.sprite.width;
  if(gScale.y < 0) gPos.y -= this.sprite.height;
};

module.exports = Frame;

'use strict';

var PIXI = window.PIXI,
    Point = require('../data/point'),
    Rect = require('../data/rect');

function Frame(position, url, options) {
  this.pos = position;
  this.dir = options.direction || new Point(1, 1);
  this.offset = options.offset || new Point(0, 0);

  var base = PIXI.BaseTexture.fromImage(url, false, PIXI.scaleModes.NEAREST),
      slice = options.crop || new Rect(0, 0, base.width, base.height),
      tex = new PIXI.Texture(base, slice);

  this.sprite = new PIXI.Sprite(tex);

  this.render();
}

Frame.prototype.render = function() {
  var gPos = this.sprite.position,
      gScale = this.sprite.scale;

  gPos.x = this.pos.x + this.offset.x;
  gPos.y = this.pos.y + this.offset.y;

  gScale.x = this.dir.x;
  gScale.y = this.dir.y;

  /*
   * Flipping will result in the sprite appearing to jump (flips on the 0,
   * rather than mid-sprite), so subtract the sprite's size from its position
   * if it's flipped.
   */

  if(gScale.x < 0) gPos.x -= this.sprite.width;
  if(gScale.y < 0) gPos.y -= this.sprite.height;
};

module.exports = Frame;

Remove deoptimized calls based on profiling


window._ = require('lodash');

/**
 * We'll load jQuery and the Bootstrap jQuery plugin which provides support
 * for JavaScript based Bootstrap features such as modals and tabs. This
 * code may be modified to fit the specific needs of your application.
 */

window.$ = window.jQuery = require('jquery');

require('bootstrap-sass');

/**
 * Vue is a modern JavaScript library for building interactive web interfaces
 * using reactive data binding and reusable components. Vue's API is clean
 * and simple, leaving you to focus on building your next great project.
 */

window.Vue = require('vue');

/**
 * We'll load the axios HTTP library which allows us to easily issue requests
 * to our Laravel back-end. This library automatically handles sending the
 * CSRF token as a header based on the value of the "XSRF" token cookie.
 */

window.axios = require('axios');

window.axios.defaults.headers.common = {
    'X-Requested-With': 'XMLHttpRequest'
};

/**
 * Echo exposes an expressive API for subscribing to channels and listening
 * for events that are broadcast by Laravel. Echo and event broadcasting
 * allows your team to easily build robust real-time web applications.
 */

// import Echo from "laravel-echo"

// window.Echo = new Echo({
//     broadcaster: 'pusher',
//     key: 'your-pusher-key'
// });

window._ = require('lodash');

/**
 * We'll load jQuery and the Bootstrap jQuery plugin which provides support
 * for JavaScript based Bootstrap features such as modals and tabs. This
 * code may be modified to fit the specific needs of your application.
 */

window.$ = window.jQuery = require('jquery');

require('bootstrap-sass');

/**
 * Vue is a modern JavaScript library for building interactive web interfaces
 * using reactive data binding and reusable components. Vue's API is clean
 * and simple, leaving you to focus on building your next great project.
 */

window.Vue = require('vue');

/**
 * We'll load the axios HTTP library which allows us to easily issue requests
 * to our Laravel back-end. This library automatically handles sending the
 * CSRF token as a header based on the value of the "XSRF" token cookie.
 */

window.axios = require('axios');

window.axios.defaults.headers.common = {
    'X-CSRF-TOKEN': window.Laravel.csrfToken,
    'X-Requested-With': 'XMLHttpRequest'
};

/**
 * Echo exposes an expressive API for subscribing to channels and listening
 * for events that are broadcast by Laravel. Echo and event broadcasting
 * allows your team to easily build robust real-time web applications.
 */

// import Echo from "laravel-echo"

// window.Echo = new Echo({
//     broadcaster: 'pusher',
//     key: 'your-pusher-key'
// });

Make axios automatically send the `X-CSRF-TOKEN`


module.exports = {
  description: 'Adds i18next dependency to the app.',

  normalizeEntityName: function () {},

  afterInstall: function(options) {
    return this.addBowerPackageToProject('i18next');
  }
};

module.exports = {
  description: 'Adds i18next dependency to the app.',

  normalizeEntityName: function () {},

  afterInstall: function(options) {
    return this.addBowerPackageToProject('i18next', '^1.7.0');
  }
};

Add version to addBowerPackageToProject call


// import polyfills. Done as an export to make sure polyfills are imported first
export * from './polyfill';

// export core
export * from './core';

// export libs
import * as accessibility from './accessibility';
import * as extract from './extract';
import * as filters from './filters';
import * as interaction from './interaction';
import * as loaders from './loaders';
import * as prepare from './prepare';
import * as audio from './audio';
import Signal from './Signal';

// handle mixins now, after all code has been added
import { utils } from './core';
utils.mixins.perform_mixins();

/**
 * Alias for {@link V.loaders.shared}.
 * @name loader
 * @memberof V
 * @type {V.loader.Loader}
 */
const loader = loaders.shared || null;

const sound = audio.SoundLibrary.init(loaders);

export {
    accessibility,
    extract,
    filters,
    interaction,
    loaders,
    prepare,
    loader,
    audio,
    sound,
    Signal,
};

import SceneTree from './SceneTree';

export * from './SceneTree';
export const scene_tree = new SceneTree();

// import polyfills. Done as an export to make sure polyfills are imported first
export * from './polyfill';

// export core
import * as core from './core';
export * from './core';

// export libs
import * as accessibility from './accessibility';
import * as extract from './extract';
import * as filters from './filters';
import * as interaction from './interaction';
import * as loaders from './loaders';
import * as prepare from './prepare';
import * as audio from './audio';
import Signal from './Signal';

// handle mixins now, after all code has been added
import { utils } from './core';
utils.mixins.perform_mixins();

/**
 * Alias for {@link V.loaders.shared}.
 * @name loader
 * @memberof V
 * @type {V.loader.Loader}
 */
const loader = loaders.shared || null;

const sound = audio.SoundLibrary.init(loaders);

export {
    accessibility,
    extract,
    filters,
    interaction,
    loaders,
    prepare,
    loader,
    audio,
    sound,
    Signal,
};

import SceneTree from './SceneTree';

export * from './SceneTree';
export const scene_tree = new SceneTree();

function assemble_node(node, children) {
    if (!children || children.length === 0) {
        return;
    }

    let i, data, inst;
    for (i = 0; i < children.length; i++) {
        data = children[i];

        inst = new (core[data.type])();
        inst._load_data(data);

        assemble_node(inst, data.children);

        node.add_child(inst);
    }
}
export function assemble_scene(scn, data) {
    if (data.name) {
        scn.name = name;
    }
    if (data.children) {
        for (let i = 0; i < data.children.length; i++) {
            assemble_node(scn, data.children);
        }
    }
    return scn;
}

Add function to assemble node from data


var util = require('util'),
    Pipeline = require('pipeline'),
    SerializationPlugin = require('./plugins/serialization');

//Modifier
var Modifier = module.exports = function (availablePlugins) {
    Pipeline.call(this);

    this.plugins.push(SerializationPlugin);

    var modifier = this;

    availablePlugins.forEach(function (plugin) {
        modifier[plugin.name] = function (replacer) {
            this._enablePlugin(plugin, replacer);
            return this;
        };
    });
};

util.inherits(Modifier, Pipeline);

//Internals
Modifier.prototype._enablePlugin = function (plugin, replacer) {
    if (!this._isPluginEnabled(plugin)) {
        var serializationPluginIdx = this.plugins.indexOf(SerializationPlugin);

        //NOTE: SerializationPlugin should be the last in the chain
        this.plugins.splice(serializationPluginIdx, 0, plugin);
        this.pluginResetArgs[plugin] = replacer;
    }
};

Modifier.prototype._aggregatePluginResults = SerializationPlugin.getHtml;

var util = require('util'),
    Pipeline = require('pipeline'),
    SerializationPlugin = require('./plugins/serialization');

//Modifier
var Modifier = module.exports = function (availablePlugins) {
    Pipeline.call(this);

    this.plugins.push(SerializationPlugin);

    var modifier = this;

    availablePlugins.forEach(function (plugin) {
        modifier[plugin.name] = function (replacer) {
            this._enablePlugin(plugin, replacer);
            return this;
        };
    });
};

util.inherits(Modifier, Pipeline);

//Internals
Modifier.prototype._aggregatePluginResults = SerializationPlugin.getHtml;

Modifier.prototype._enablePlugin = function (plugin, replacer) {
    if (!this._isPluginEnabled(plugin)) {
        var serializationPluginIdx = this.plugins.indexOf(SerializationPlugin);

        //NOTE: SerializationPlugin should be the last in the chain
        this.plugins.splice(serializationPluginIdx, 0, plugin);
        this.pluginResetArgs[plugin] = replacer;
    }
};

Swap code lines FTW =)


import React from 'react'

import {iconify} from '../lib/str'
import styles from './styles'

export const Link = ({name, href, title}) => (

)

export const Header = () => (

Langri-Sha

      {[
        [
          'Stack Overflow', 'https://stackoverflow.com/users/44041/filip-dupanovi%C4%87?tab=profile',
          'StackOverflow profile #SOreadytohelp 💓'
        ],
        [
          'Keybase', 'https://keybase.io/langrisha',
          'Identity details on Keybase.io'
        ],
        [
          'GitHub', 'https://github.com/langri-sha',
          'GitHub profile'
        ]
      ].map(([name, href, title]) => (
        <Link key={name} name={name} href={href} title={title} />
      ))}

)

import React from 'react'

import {iconify} from '../lib/str'
import styles from './styles'

export const Link = ({name, href, title}) => (

)

export const Header = () => (

Langri-Sha

      {[
        [
          'Stack Overflow', 'https://stackoverflow.com/users/44041/filip-dupanovi%C4%87?tab=profile',
          'StackOverflow profile #SOreadytohelp 💓'
        ],
        [
          'Keybase', 'https://keybase.io/langrisha',
          'Identity details on Keybase.io'
        ],
        [
          'GitHub', 'https://github.com/langri-sha',
          'GitHub profile'
        ],
        [
          'Docker', 'https://hub.docker.com/u/langrisha/',
          'Docker Hub profile'
        ]
      ].map(([name, href, title]) => (
        <Link key={name} name={name} href={href} title={title} />
      ))}

)

Add link to Docker Hub :rocket:


module.exports = {
    tabWidth: 4,
    printWidth: 100,
    singleQuote: true,
    arrowParens: "always",
    trailingComma: "all",

    overrides: [
        {
            files: ["*.json"],
            options: {
                parser: "json",
                tabWidth: 2,
                singleQuote: false,
            },
        },
        {
            files: ["*.yml"],
            options: {
                parser: "yml",
                tabWidth: 2,
                singleQuote: false,
            },
        },
    ],
};

module.exports = {
    tabWidth: 4,
    printWidth: 100,
    singleQuote: true,
    arrowParens: "always",
    trailingComma: "all",

    overrides: [
        {
            files: ["*.json"],
            options: {
                parser: "json",
                tabWidth: 2,
                singleQuote: false,
            },
        },
        {
            files: ["*.yml"],
            options: {
                parser: "yml",
                tabWidth: 2,
                singleQuote: false,
            },
        },
        {
            files: ["*.css"],
            options: {
                parser: "css",
                singleQuote: false,
            },
        },
        {
            files: ["*.scss"],
            options: {
                parser: "scss",
                singleQuote: false,
            },
        },
    ],
};

Add stylesheets rules for Prettier


'use strict';

/* Services */

// Demonstrate how to register services
// In this case it is a simple value service.
angular.module('myApp.services', []).
  value('version', '0.1')
  .factory("moviesService", function($http){
    var _movies = [];

    var _getMovies = function(){
        $http.get("js/data/movies.json")
            .then(function(results){
                //Success
                angular.copy(results.data, _movies); //this is the preferred; instead of $scope.movies = result.data
            }, function(results){
                //Error
            })
    }

    var _addNewMovie = function(movie){
        _movies.splice(0, 0, movie);
    }
    var _removeMovie = function(idx){
    	var person_to_delete = _movies[idx.id];
    	_movies.splice(idx.id, 1);
    	/*
    	angular.forEach(_movies, function(value, key){
    		if(value.id == movie.id){
	  		   _movies.splice(idx, 1);
  		  	}
    	});
    	*/
    }

    return{
        movies: _movies,
        getMovies: _getMovies,
        addNewMovie: _addNewMovie,
        removeMovie:_removeMovie
    };
});

'use strict';

/* Services */

// Demonstrate how to register services
// In this case it is a simple value service.
angular.module('myApp.services', []).
  value('version', '0.1')
  .factory("moviesService", function($http){
    var _movies = [];

    var _getMovies = function(){
        $http.get("js/data/movies.json")
            .then(function(results){
                //Success
                angular.copy(results.data, _movies); //this is the preferred; instead of $scope.movies = result.data
            }, function(results){
                //Error
            })
    }

    var _addNewMovie = function(movie){
        _movies.splice(0, 0, movie);
    }
    var _removeMovie = function(idx){
    	var person_to_delete = _movies[idx.id];
    	_movies.splice(idx.id, 1);
    	/*
    	angular.forEach(_movies, function(value, key){
    		if(value.id == movie.id){
	  		   _movies.splice(idx, 1);
  		  	}
    	});
    	*/
    }

    return{
        movies: _movies,   // revealing module pattern applied here
        getMovies: _getMovies,
        addNewMovie: _addNewMovie,
        removeMovie:_removeMovie
    };
});

Comment for revealing module pattern


'use strict';

angular.module('Teem')
  .directive('participate', function() {
    return {
      controller: [
      '$scope', '$element', '$attrs', 'SessionSvc', '$timeout', 'CommunitiesSvc',
      function($scope, $element, $attrs, SessionSvc, $timeout, CommunitiesSvc) {
        $scope.participateCopyOn  = $attrs.participateCopyOn;
        $scope.participateCopyOff = $attrs.participateCopyOff;

        $element.on('click', function($event) {
          SessionSvc.loginRequired($scope, function() {
            if ($scope.community.toggleParticipant) {
              $timeout(function() {
                $scope.community.toggleParticipant();
              });
            } else {
              CommunitiesSvc.find($scope.community.id).then(function(community) {
                $timeout(function() {
                  community.toggleParticipant();
                });
              });
            }
          });
          $event.stopPropagation();
        });
      }],
      templateUrl: 'participate.html'
    };
  });

'use strict';

angular.module('Teem')
  .directive('participate', function() {
    return {
      controller: [
      '$scope', '$element', '$attrs', 'SessionSvc', '$timeout', 'CommunitiesSvc',
      function($scope, $element, $attrs, SessionSvc, $timeout, CommunitiesSvc) {
        $scope.participateCopyOn  = $attrs.participateCopyOn;
        $scope.participateCopyOff = $attrs.participateCopyOff;

        $element.on('click', function($event) {
          SessionSvc.loginRequired($scope, function() {
            if ($scope.community.toggleParticipant) {
              $timeout(function() {
                $scope.community.toggleParticipant();
              });
            } else {
              CommunitiesSvc.find($scope.community.id).then(function(community) {
                $timeout(function() {
                  community.toggleParticipant();
                });
              });
            }
          });
        });
      }],
      templateUrl: 'participate.html'
    };
  });

Stop propatation here not longer needed


var config = require('/opt/cocorico/api-web/config.json');

var keystone = require('keystone');
var transform = require('model-transform');
var bcrypt = require('bcrypt');

var Types = keystone.Field.Types;

var Ballot = new keystone.List('Ballot', {
  defaultSort: '-updatedAt',
  track: { createdAt: true, updatedAt: true },
  nodelete: config.env !== 'development',
  nocreate: true,
  noedit: true,
});

Ballot.add({
  status: {
    type: Types.Select,
    options: [
      'signing',
      'queued',
      'pending',
      'initialized',
      'registered',
      'complete',
      'error',
    ],
    default: 'queued',
    required: true,
    initial: true,
  },
  hash: { type: String, required: true, initial: true },
  error: { type: String },
});

transform.toJSON(Ballot);

Ballot.defaultColumns = 'status, hash, createdAt, updatedAt';
Ballot.register();

var config = require('/opt/cocorico/api-web/config.json');

var keystone = require('keystone');
var transform = require('model-transform');

var Types = keystone.Field.Types;

var Ballot = new keystone.List('Ballot', {
  defaultSort: '-updatedAt',
  track: { createdAt: true, updatedAt: true },
  nodelete: config.env !== 'development',
  nocreate: true,
  noedit: true,
});

Ballot.add({
  status: {
    type: Types.Select,
    options: [
      'signing',
      'queued',
      'pending',
      'initialized',
      'registered',
      'complete',
      'error',
    ],
    default: 'queued',
    required: true,
    initial: true,
  },
  hash: { type: String, required: true, initial: true },
  error: { type: String },
});

transform.toJSON(Ballot);

Ballot.defaultColumns = 'status, hash, createdAt, updatedAt';
Ballot.register();

Fix unused required of the 'bcrypt' module.


import ApplicationAdapter from 'ember-jsonapi-resources/adapters/application';

export default ApplicationAdapter.extend({
  type: 'proposal',

  url: /*config.APP.API_PATH + */ '/proposals',

  /*fetchUrl: function(url) {
    const proxy = config.APP.API_HOST_PROXY;
    const host = config.APP.API_HOST;
    if (proxy && host) {
      url = url.replace(proxy, host);
    }
    return url;
  }*/
});

import ApplicationAdapter from 'ember-jsonapi-resources/adapters/application';
import config from '../config/environment';

export default ApplicationAdapter.extend({
  type: 'proposal',

  url: config.APP.API_HOST +  '/proposals',

  // FIXME: This is a hack to make ember-jsonapi-resources work with ember-simple-auth.
  // It overrides fetch() options to include the bearer token in the session.
  // I'll post an issue on ember-jsonapi-resources and see if there's a better way.
  fetchOptions(options) {
    let isUpdate;
    options.headers = options.headers || { 'Content-Type': 'application/vnd.api+json' };
    // const authHeader = window.localStorage.getItem('AuthorizationHeader');
    const simpleAuthSession = JSON.parse(window.localStorage.getItem('ember_simple_auth:session'));
    const accessToken       = simpleAuthSession.secure.access_token;
    const authHeader        = 'Bearer ' + accessToken;

    if (authHeader) {
      options.headers['Authorization'] = authHeader;
    }
    if (typeof options.update === 'boolean') {
      isUpdate = options.update;
      delete options.update;
    }
    return isUpdate;
  }
});

Make ember-jsonapi-resources work with ember-simple-auth, by overriding fetch() options to include the bearer token in the session.


;var conpigurator = {
	active:false,
	handleChange:function(event){
		if($(event.target).hasClass('conpiguratorInput')){
			if(event.target.value && event.target.value !== '' && typeof event.target.value === 'string'){
				if(event.target.dataset){
					var pigment = event.target.value;
					if(pigment.substring(0,1) !== '#') pigment = '#'+pigment;
					pigment = (pigment.length > 7)? pigment.substring(0,7) : pigment;
					conpigurator.conpigurateElements(event.target.dataset.conpigbg,'backgroundColor',pigment);
					conpigurator.conpigurateElements(event.target.dataset.conpigborder,'borderColor',pigment);
					conpigurator.conpigurateElements(event.target.dataset.conpigtext,'color',pigment);
				}
			}
		}
	},
	conpigurateElements:function(selector,colorProperty,pigment){
		if(selector){
			colorProperty = colorProperty || 'backgroundColor';
			$(selector).css(colorProperty,pigment);
		}
	},
	init:function(){
		if(!conpigurator.active){
			$(body).on('change',function(event){conpigurator.handleChange(event);});
			conpigurator.active = true;
		}
	}
};

;var conpigurator = {
	active:false,
	handleChange:function(event){
		if($(event.target).hasClass('conpiguratorInput')){
			if(event.target.value && event.target.value !== '' && typeof event.target.value === 'string'){
				if(event.target.dataset){
					var pigment = event.target.value;
					if(pigment.substring(0,1) !== '#') pigment = '#'+pigment;
					pigment = (pigment.length > 7)? pigment.substring(0,7) : pigment;
					conpigurator.conpigurateElements(event.target.dataset.conpigbg,'backgroundColor',pigment);
					conpigurator.conpigurateElements(event.target.dataset.conpigborder,'borderColor',pigment);
					conpigurator.conpigurateElements(event.target.dataset.conpigtext,'color',pigment);
				}
			}
		}
	},
	conpigurateElements:function(selector,colorProperty,pigment){
		if(selector){
			colorProperty = colorProperty || 'backgroundColor';
			$(selector).css(colorProperty,pigment);
		}
	},
	init:function(){
		if(!conpigurator.active){
			$('body').on('change',function(event){conpigurator.handleChange(event);});
			conpigurator.active = true;
		}
	}
};

Fix 'body' selector in init function


import React from 'react';
import { connect } from 'react-redux';
import Grid from 'react-bootstrap/lib/Grid';
import Errors from '../../constants/Errors';
import { removeError } from '../../actions/errorActions';

let ErrorList = ({ errors, dispatch }) => (
  <Grid>
    {errors.map((error) => (

        <button
          type="button"
          className="close"
          data-dismiss="alert"
          aria-label="Close"
          onClick={() => dispatch(removeError(error.id))}
        >
          ×
        </button>
        {error.title}
        {' ' + error.detail}
        {error.meta && [(

            {error.code === Errors.STATE_PRE_FETCHING_FAIL.code && (
              {error.meta.detail}
            )}

        ), (

            {error.meta.path && `(at path '${error.meta.path}')`}

        )]}

    ))}
  </Grid>
);

export default connect(state => ({
  errors: state.errors,
}))(ErrorList);

import React from 'react';
import { connect } from 'react-redux';
import Grid from 'react-bootstrap/lib/Grid';
import Errors from '../../constants/Errors';
import { removeError } from '../../actions/errorActions';

let ErrorList = ({ errors, dispatch }) => (
  <Grid>
    {errors.map((error) => (

        <button
          type="button"
          className="close"
          data-dismiss="alert"
          aria-label="Close"
          onClick={() => dispatch(removeError(error.id))}
        >
          ×
        </button>
        {error.title}
        {' ' + error.detail}
        {error.meta && [(

            {error.code === Errors.STATE_PRE_FETCHING_FAIL.code && (
              {error.meta.detail}
            )}

        ), (

            {error.meta.path && `(at path '${error.meta.path}')`}

        ), (

            {error.code === Errors.UNKNOWN_EXCEPTION.code && (
              {error.meta.toString()}
            )}

        )]}

    ))}
  </Grid>
);

export default connect(state => ({
  errors: state.errors,
}))(ErrorList);

Add UI for unknow exception


var express = require('express');
var router = express.Router();

var models = require('../../models/index');
var ZiviService = require('../../services/zivi.service');

router.get('/', function (req, res) {
  models.Zivi.find({}).sort('order').exec(function(err, response){
    return res.json({
      zivicount: response.length,
      zivis: response
    });
  });
});

router.get('/random', function (req, res) {
  models.Zivi.find({}).then(function(response){
    return res.json(response[Math.floor(Math.random() * response.length)])
  });
});

module.exports = router;

var express = require('express');
var router = express.Router();

var models = require('../../models/index');
var ZiviService = require('../../services/zivi.service');

router.get('/', function (req, res) {
  models.Zivi.find({}).sort('order').exec(function(err, response){
    return res.json({
      zivicount: response.length,
      zivis: response
    });
  });
});

router.get('/random', function (req, res) {
  models.Zivi.find({}).then(function(response){
    return res.json(response[Math.floor(Math.random() * response.length)])
  });
});

router.post('/delete', function (req, res) {
  var name = req.body.name;
  if(!name) {
    return res.status(400).json({error: "No name given"});
  }
  var zivi = ZiviService.findOneByName(name, function (zivi) {
    ZiviService.deleteZivi(zivi, function (err) {
      if(err) {
        return res.status(500).json({error: err});
      } else {
        return res.status(200).json({error: false});
      }
    })
  });
});

module.exports = router;

Add zivi delete by name API


'use strict';

var expect = require('chai').expect;
var VariableCollection = require('../app/scripts/variable-collection');
var Variable = require('../app/scripts/variable');

describe('variable collection', function () {

  it('should initialize with list of variables', function () {
    var variables = new VariableCollection({
      items: [
        {name: 'u'},
        {name: 'v'},
      ]
    });
    expect(variables).to.have.property('items');
    expect(variables.items).to.have.length(2);
    variables.items.forEach(function (variable) {
      expect(variable).to.be.an.instanceof(Variable);
    });
  });

});

'use strict';

var expect = require('chai').expect;
var VariableCollection = require('../app/scripts/variable-collection');
var Variable = require('../app/scripts/variable');

describe('variable collection', function () {

  it('should initialize with list of variables', function () {
    var variables = new VariableCollection({
      items: [
        {name: 'u'},
        {name: 'v'},
      ]
    });
    expect(variables).to.have.property('items');
    expect(variables.items).to.have.length(2);
    variables.items.forEach(function (variable) {
      expect(variable).to.be.an.instanceof(Variable);
    });
  });

  it('should serialize to a JSON object', function () {
    var variables = new VariableCollection({
      items: [{name: 'u'},{name: 'v'}]
    });
    expect(variables.serialize()).to.deep.equal({
      items: [{name: 'u'},{name: 'v'}]
    });
  });

});

Add test for variable collection serialization


'use strict';

const { EventEmitter } = require('events');
const { Browser, Devices } = require('../lib/discovery');

function asFilter(filter) {
	if(typeof filter === 'string') {
		return reg => reg.id === filter || reg.address === filter;
	} else if(typeof filter === 'function') {
		return filter;
	} else {
		return () => true;
	}
}

function asToplevelFilter(filter) {
	return reg => reg.type === 'gateway' || filter(reg);
}

module.exports = function(options) {
	const filter = asFilter(options.filter);
	let browser;
	if(options.instances) {
		browser = new Devices({
			cacheTime: options.cacheTime || 300,
			filter: options.filter ? asToplevelFilter(filter) : null
		});
	} else {
		browser = new Browser({
			cachetime: options.cacheTime || 300
		});
	}

	const result = new EventEmitter();
	browser.on('available', reg => {
		if(filter(reg)) {
			result.emit('available', reg);
		}
	});
	browser.on('unavailable', reg => result.emit('unavailable', reg));
	return result;
};

'use strict';

const { EventEmitter } = require('events');
const { Browser, Devices } = require('../lib/discovery');

function asFilter(filter) {
	if(typeof filter === 'string') {
		return reg => reg.id === filter || reg.address === filter || reg.model === filter || reg.type === filter;
	} else if(typeof filter === 'function') {
		return filter;
	} else {
		return () => true;
	}
}

function asToplevelFilter(filter) {
	return reg => reg.type === 'gateway' || filter(reg);
}

module.exports = function(options) {
	const filter = asFilter(options.filter);
	let browser;
	if(options.instances) {
		browser = new Devices({
			cacheTime: options.cacheTime || 300,
			filter: options.filter ? asToplevelFilter(filter) : null
		});
	} else {
		browser = new Browser({
			cachetime: options.cacheTime || 300
		});
	}

	const result = new EventEmitter();
	browser.on('available', reg => {
		if(filter(reg)) {
			result.emit('available', reg);
		}
	});
	browser.on('unavailable', reg => result.emit('unavailable', reg));
	return result;
};

Allow CLI to find devices based on model and type


var mongoose = require('mongoose');

var dbURI = 'mongodb://localhost/Loc8r';
mongoose.connect(dbURI);

mongoose.connection.on('connected', function() {
    console.log('Mongoose connected to ' + dbURI);
});

mongoose.connection.on('error', function(err) {
    console.log('Mongoose connection error:' + err);
});

mongoose.connection.on('disconnected', function() {
    console.log('Mongoose disconnected');
});

var gracefulShutdown = function(msg, callback) {
    mongoose.connection.close(function() {
        console.log('Mongoose disconnected through ' + msg);
        callback();
    })
};

process.once('SIGUSR2', function() {
    gracefulShutdown('nodemon restart', function() {
        process.kill(process.pid, 'SIGUSR2');
    });
});

process.once('SIGINT', function() {
    gracefulShutdown('app termination', function() {
        process.exit(0);
    });
});

process.once('SIGTERM', function() {
    gracefulShutdown('Heroku app shutdown', function() {
        process.exit(0);
    });
});

require('./locations');

var mongoose = require('mongoose');

var dbURI = (process.env.NODE_ENV === 'production')
    ? process.env.MONGOLAB_URI
    : 'mongodb://localhost/Loc8r';

mongoose.connect(dbURI);

mongoose.connection.on('connected', function() {
    console.log('Mongoose connected to ' + dbURI);
});

mongoose.connection.on('error', function(err) {
    console.log('Mongoose connection error:' + err);
});

mongoose.connection.on('disconnected', function() {
    console.log('Mongoose disconnected');
});

var gracefulShutdown = function(msg, callback) {
    mongoose.connection.close(function() {
        console.log('Mongoose disconnected through ' + msg);
        callback();
    })
};

process.once('SIGUSR2', function() {
    gracefulShutdown('nodemon restart', function() {
        process.kill(process.pid, 'SIGUSR2');
    });
});

process.once('SIGINT', function() {
    gracefulShutdown('app termination', function() {
        process.exit(0);
    });
});

process.once('SIGTERM', function() {
    gracefulShutdown('Heroku app shutdown', function() {
        process.exit(0);
    });
});

require('./locations');

Make the app use the right database