var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
var config = require('../config');

gulp.task('watch', ['browserify:build', 'scripts:watch', 'sass:watch', 'templates:watch', 'views:watch']);
gulp.task('build', ['browserify:build', 'scripts:build', 'sass:build', 'templates:build', 'views:build']);
gulp.task('lint', ['scripts:lint']);
gulp.task('clean', ['browserify:clean', 'scripts:clean', 'sass:clean', 'templates:clean']);

gulp.task('serve', config.production ? null : ['watch'], function () {
    $.connect.server({
        root: config.serve.root,
        livereload: !config.production,
        port: config.serve.port
    });
});

gulp.task('default', ['serve']);

var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
var config = require('../config');

gulp.task('watch', ['scripts:watch', 'sass:watch', 'templates:watch', 'views:watch']);
gulp.task('build', ['browserify:build', 'scripts:build', 'sass:build', 'templates:build', 'views:build']);
gulp.task('lint', ['scripts:lint']);
gulp.task('clean', ['browserify:clean', 'scripts:clean', 'sass:clean', 'templates:clean']);

gulp.task('serve', config.production ? ['build'] : ['build', 'watch'], function () {
    $.connect.server({
        root: config.serve.root,
        livereload: !config.production,
        port: config.serve.port
    });
});

gulp.task('default', ['serve']);

Add build to gulp serve task dependencies.


/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

var gulp = require('gulp');
var ts = require('gulp-typescript');
var typescript = require('typescript');
var gutil = require('gulp-util');
var filter = require('gulp-filter');
var merge = require('merge2');

var tsProject = ts.createProject('./tsconfig.json', {
  typescript: typescript,
  noExternalResolve: true, // opt-in for faster compilation!
});

module.exports = function() {
  var isComponent = filter([
    'components/tf-*/**/*.ts',
    'components/vz-*/**/*.ts',
    'typings/**/*.ts',
    // TODO(danmane): add plottable to the typings registry after updating it
    // and remove this.
    'components/plottable/plottable.d.ts'
  ]);

  return tsProject.src()
           .pipe(isComponent)
           .pipe(ts(tsProject))
           .js
            .pipe(gulp.dest('.'));

}

/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

var gulp = require('gulp');
var ts = require('gulp-typescript');
var typescript = require('typescript');
var gutil = require('gulp-util');
var filter = require('gulp-filter');
var merge = require('merge2');

var tsProject = ts.createProject('./tsconfig.json', {
  typescript: typescript,
  noExternalResolve: true, // opt-in for faster compilation!
});

module.exports = function() {
  var isComponent = filter([
    'components/tf-*/**/*.ts',
    'components/vz-*/**/*.ts',
    'typings/**/*.ts',
    'components/plottable/plottable.d.ts'
  ]);

  return tsProject.src()
           .pipe(isComponent)
           .pipe(ts(tsProject))
           .js
            .pipe(gulp.dest('.'));

}

Remove the plottable typings todo as it is currently a good solution Change: 130777731


angular.module('nameApp', [])
    .factory('PersonsService', personsService)
    .directive('name', nameDirective)
    .controller('ExampleCtrl', ExampleCtrl);

ExampleCtrl.$inject = ['PersonsService'];

function ExampleCtrl(PersonsService) {
    var ctrl = this;
    PersonsService.get(function(data) {
        ctrl.persons = data;
    });
    ctrl.max = 4;
}

personsService.$inject = ['$http'];

function personsService($http) {
    var service = {
        get: get_all,
    };
    return service;

    function get_all(callback) {
        $http.get('/examples/28/names.json').then(function(response) {
            callback(response.data);
        });
    }
}

NameDirectiveCtrl.$inject = ['$scope'];

function NameDirectiveCtrl($scope) {
    $scope.remove = function(person) {
        $scope.persons = $scope.persons.filter(function(p) {
            if (p !== person) {
                return true;
            }
            return false;
        });
    };
}

function nameDirective() {
    return {
        restrict: 'AE',
        templateUrl: '/examples/29/name.html',
        controller: NameDirectiveCtrl,
        scope: {
            person: '=person',
            persons: '=all',
        },
    };

}

angular.module('nameApp', [])
    .factory('PersonsService', personsService)
    .directive('name', nameDirective)
    .controller('ExampleCtrl', ExampleCtrl);

ExampleCtrl.$inject = ['PersonsService'];

function ExampleCtrl(PersonsService) {
    var ctrl = this;
    PersonsService.get(function(data) {
        ctrl.persons = data;
    });
    ctrl.max = 4;
}

personsService.$inject = ['$http'];

function personsService($http) {
    var service = {
        get: get_all,
    };
    return service;

    function get_all(callback) {
        $http.get('/examples/29/names.json').then(function(response) {
            callback(response.data);
        });
    }
}

NameDirectiveCtrl.$inject = ['$scope'];

function NameDirectiveCtrl($scope) {
    $scope.remove = function(person) {
        $scope.persons = $scope.persons.filter(function(p) {
            if (p !== person) {
                return true;
            }
            return false;
        });
    };
}

function nameDirective() {
    return {
        restrict: 'AE',
        templateUrl: '/examples/29/name.html',
        controller: NameDirectiveCtrl,
        scope: {
            person: '=person',
            persons: '=all',
        },
    };

}

Fix loading names.json for example 29


import React from 'react';
import './paging-buttons.scss';

class PagingButtons extends React.Component {
  render() {
    const prev = this.props.prev;
    const next = this.props.next;

    return (

         this.props.onPaginate(prev, e)} disabled={prev}>{prev ? "< previous" : null}

           this.props.onPaginate(next, e)}>{next ? "next >" : null}

    )
  }
}

export default PagingButtons;

import React from 'react';
import PropTypes from 'prop-types';

import './paging-buttons.scss';

class PagingButtons extends React.Component {
  render() {
    const prev = this.props.prev;
    const next = this.props.next;

    return (

         this.props.onPaginate(prev, e)} disabled={prev}>{prev ? "< previous" : null}

           this.props.onPaginate(next, e)}>{next ? "next >" : null}

    )
  }
}

PagingButtons.propTypes = {
  next: PropTypes.string.isRequired,
  onPaginate: PropTypes.func.isRequired,
  prev: PropTypes.string.isRequired,
};

export default PagingButtons;

Add proptype validation to PagingButtons component


// ==UserScript==
// @name        VLC Remote
// @namespace   fatmonkeys
// @include     http://[IP address of VLC Remote server]:8080/
// @version     1
// @grant       none
// ==/UserScript==

document.onkeypress = checkKey;

function eventFire(el, etype){
  if (el.fireEvent) {
    el.fireEvent('on' + etype);
  } else {
    var evObj = document.createEvent('Events');
    evObj.initEvent(etype, true, false);
    el.dispatchEvent(evObj);
  }
}

function checkKey(e) {
    e = e || window.event;
    if (e.charCode == 32) {
      eventFire(document.getElementById('buttonPlay'), 'click');
    } else if(e.ctrlKey && e.keyCode == 37) {
      eventFire(document.getElementById('buttonPrev'), 'mousedown');
      eventFire(document.getElementById('buttonPrev'), 'mouseup');
    } else if(e.ctrlKey && e.keyCode == 39) {
      eventFire(document.getElementById('buttonNext'), 'mousedown');
      eventFire(document.getElementById('buttonNext'), 'mouseup');
    }
}

// ==UserScript==
// @name        VLC Remote
// @namespace   fatmonkeys
// @include     http://[IP address of VLC Remote server]:8080/
// @version     1
// @grant       none
// ==/UserScript==

// Enables new keyboard shortcuts:
// Space to pause/resume the current video.
// Ctrl + Right arrow to jump to the next video in the playlist.
// Ctrl + Left arrow to jump to the previous video in the playlist.

document.onkeypress = checkKey;

function eventFire(el, etype){
  if (el.fireEvent) {
    el.fireEvent('on' + etype);
  } else {
    var evObj = document.createEvent('Events');
    evObj.initEvent(etype, true, false);
    el.dispatchEvent(evObj);
  }
}

function checkKey(e) {
    e = e || window.event;
    if (e.charCode == 32) {
      eventFire(document.getElementById('buttonPlay'), 'click');
    } else if(e.ctrlKey && e.keyCode == 37) {
      eventFire(document.getElementById('buttonPrev'), 'mousedown');
      eventFire(document.getElementById('buttonPrev'), 'mouseup');
    } else if(e.ctrlKey && e.keyCode == 39) {
      eventFire(document.getElementById('buttonNext'), 'mousedown');
      eventFire(document.getElementById('buttonNext'), 'mouseup');
    }
}

Document shortcuts for VLC Remote


'use strict';

var Ajv = require(typeof window == 'object' ? 'ajv' : '../lib/ajv')
  , should = require('chai').should()
  , stableStringify = require('json-stable-stringify');

describe('Ajv Options', function () {

  describe('removeAdditional', function() {
    it('should remove properties that would error when `additionalProperties = false`', function() {
      var ajv = Ajv({ removeAdditional: true });

      ajv.compile({
        id: '//test/fooBar',
        properties: { foo: { type: 'string' }, bar: { type: 'string' } },
        additionalProperties: false
      });

      var object = {
        foo: 'foo', bar: 'bar', baz: 'baz-to-be-removed'
      };

      ajv.validate('//test/fooBar', object) .should.equal(true);
      object.should.have.all.keys(['foo', 'bar']);
      object.should.not.have.property('baz');

    });

  });

});

'use strict';

var Ajv = require(typeof window == 'object' ? 'ajv' : '../lib/ajv')
  , should = require('chai').should()
  , stableStringify = require('json-stable-stringify');

describe('Ajv Options', function () {

  describe('removeAdditional', function() {

    it('should remove properties that would error when `additionalProperties = false`', function() {
      var ajv = Ajv({ removeAdditional: true });

      ajv.compile({
        id: '//test/fooBar',
        properties: { foo: { type: 'string' }, bar: { type: 'string' } },
        additionalProperties: false
      });

      var object = {
        foo: 'foo', bar: 'bar', baz: 'baz-to-be-removed'
      };

      ajv.validate('//test/fooBar', object).should.equal(true);
      object.should.have.property('foo');
      object.should.have.property('bar');
      object.should.not.have.property('baz');

    });

    it('should remove properties that would error when `additionalProperties` is a schema', function() {
      var ajv = Ajv({ removeAdditional: true });

      ajv.compile({
        id: '//test/fooBar',
        properties: { foo: { type: 'string' }, bar: { type: 'string' } },
        additionalProperties: { type: 'string' }
      });

      var object = {
        foo: 'foo', bar: 'bar', baz: 'baz-to-be-kept', fizz: 1000
      };

      ajv.validate('//test/fooBar', object).should.equal(true);
      object.should.have.property('foo');
      object.should.have.property('bar');
      object.should.have.property('baz');
      object.should.not.have.property('fizz');

    });

  });

});

Add test for `removeAdditional` when using a schema to validate additional properties.


'use babel'

SoftWrapIndicator = require('../lib/soft-wrap-indicator')

describe('SoftWrapIndicatorPackage', () => {
  let atomEnv, indicator

  beforeEach(async () => {
    atomEnv = global.buildAtomEnvironment()
    let workspace = atomEnv.workspace
    let workspaceElement = atomEnv.views.getView(workspace)

    await atomEnv.packages.activatePackage('status-bar')
    await atomEnv.packages.activatePackage('language-javascript')
    await atomEnv.packages.activatePackage('language-gfm')
    await atomEnv.packages.activatePackage('soft-wrap-indicator')

    expect(SoftWrapIndicator.deactivate).to.be.ok
    indicator = SoftWrapIndicator.component.element
  })

  afterEach(() => {
    atomEnv.destroy()
  })

  it('creates an indicator element', () => {
    expect(indicator).to.be.ok
  })
})

'use babel'

SoftWrapIndicator = require('../lib/soft-wrap-indicator')

describe('SoftWrapIndicatorPackage', function () {
  let atomEnv, indicator

  beforeEach(async function () {
    await atom.packages.activatePackage('status-bar')
    await atom.packages.activatePackage('language-javascript')
    await atom.packages.activatePackage('language-gfm')
    await atom.packages.activatePackage('soft-wrap-indicator')

    expect(SoftWrapIndicator.deactivate).to.be.ok
    indicator = SoftWrapIndicator.component.element
  })

  afterEach(function () {
    atom.destroy()
  })

  it('creates an indicator element', function () {
    expect(indicator).to.be.ok
  })
})

Switch to using function keyword instead of arrow functions


import React from 'react';
import css from './FilterPaneSearch.css';
import Icon from '@folio/stripes-components/lib/Icon';
import Button from '@folio/stripes-components/lib/Button';

class FilterPaneSearch extends React.Component{
  constructor(props){
    super(props);
    this.searchInput = null;
  }

  clearSearchField(){
    this.searchInput.value = '';
    const evt =  new Event('input', {bubbles: true});
    this.searchInput.dispatchEvent(evt);
  }

  onChange() {
    console.log("changed: new value =", this.searchInput.value);
    // XXX We need to somehow feed the changed value into stripes-connect for the parent component
  }

  render(){
    return(

<Icon icon="search"/>

        <input className={css.headerSearchInput} ref={(ref) => this.searchInput = ref} type="text" value = {this.props.value} onChange={this.onChange.bind(this)} placeholder="Search"/>
        <Button className={css.headerSearchClearButton} onClick={this.clearSearchField.bind(this)} ><Icon icon="clearX" iconClassName={css.clearIcon}/></Button>

    );
  }
}

export default FilterPaneSearch;

import React, { PropTypes } from 'react';
import css from './FilterPaneSearch.css';
import Icon from '@folio/stripes-components/lib/Icon';
import Button from '@folio/stripes-components/lib/Button';

class FilterPaneSearch extends React.Component{
  static contextTypes = {
    router: PropTypes.object.isRequired
  };

  constructor(props){
    super(props);
    this.searchInput = null;
  }

  clearSearchField(){
    this.searchInput.value = '';
    const evt =  new Event('input', {bubbles: true});
    this.searchInput.dispatchEvent(evt);
  }

  onChange() {
    const value = this.searchInput.value;
    this.context.router.transitionTo("/users/" + value);
  }

  render(){
    return(

<Icon icon="search"/>

        <input className={css.headerSearchInput} ref={(ref) => this.searchInput = ref} type="text" value = {this.props.value} onChange={this.onChange.bind(this)} placeholder="Search"/>
        <Button className={css.headerSearchClearButton} onClick={this.clearSearchField.bind(this)} ><Icon icon="clearX" iconClassName={css.clearIcon}/></Button>

    );
  }
}

export default FilterPaneSearch;

Set the URL to include the modified query. Part of STRIPES-85.


"use strict";

var invariant = require('react/lib/invariant');

invariant(
  window.google || window.google.maps,
  '`google.maps` global object not found, make sure ' +
    'Google maps in included before react-googlemaps is defined'
);

module.exports = window.google.maps;

"use strict";

var invariant = require('react/lib/invariant');

invariant(
  window.google && window.google.maps,
  '`google.maps` global object not found, make sure ' +
    'Google maps in included before react-googlemaps is defined'
);

module.exports = window.google.maps;

Fix logic for checking google maps exists


define(function(require, exports, mod) {

  var test = require('../../../test')

  test.assert(seajs.config() === seajs, 'sea.config is chainable')
  test.assert(seajs.emit() === seajs, 'sea.emit is chainable')
  test.assert(seajs.on() === seajs, 'sea.on is chainable')
  test.assert(seajs.off() === seajs, 'sea.off is chainable')
  test.assert(seajs.log() === undefined, 'sea.log is NOT chainable')
  test.assert(seajs.use() === seajs, 'sea.use is chainable')
  test.assert(seajs.cwd(seajs.cwd()) === seajs.cwd(), 'sea.cwd is NOT chainable')

  //seajs.log(require.resolve('./a'))

  test.assert(require.async('./a') === require, 'require.async is chainable')
  test.assert(mod.load('./a') === undefined, 'module.load is NOT chainable')

  test.next()

});

define(function(require, exports, mod) {

  var test = require('../../../test')

  test.assert(seajs.config() === seajs, 'sea.config is chainable')
  test.assert(seajs.emit() === seajs, 'sea.emit is chainable')
  test.assert(seajs.on() === seajs, 'sea.on is chainable')
  test.assert(seajs.off() === seajs, 'sea.off is chainable')
  test.assert(seajs.log() === undefined, 'sea.log is NOT chainable')
  test.assert(seajs.use() === seajs, 'sea.use is chainable')
  test.assert(seajs.cwd(seajs.cwd()) === seajs.cwd(), 'sea.cwd is NOT chainable')

  //seajs.log(require.resolve('./a'))

  test.assert(require.async('./a') === require, 'require.async is chainable')
  //test.assert(mod.load('./a') === undefined, 'module.load is NOT chainable')

  test.next()

});

Remove specs for module.load function


'use strict'

const path = require('path')
const rtfRenderer = require('../lib/')
const execa = require('execa')

module.exports = function codeHighlight(clipboard, settings) {
  const fontface = settings.getSync('fontface')
  const theme = settings.getSync('theme')
  const input = clipboard.readText()
  const output = rtfRenderer.highlightAuto(input, {
    fontface,
    theme
  }).value
  clipboard.writeRTF(output)

  // Pasting into the active application
  execa('osascript', [path.resolve('./src/paste.as')]).then((result) => {
    console.log(result.stdout)
  })
}

'use strict'

const path = require('path')
const rtfRenderer = require('../lib/')
const execa = require('execa')

module.exports = function codeHighlight(clipboard, settings) {
  const fontface = settings.getSync('fontface')
  const theme = settings.getSync('theme')
  const input = clipboard.readText()
  const output = rtfRenderer.highlightAuto(input, {
    fontface,
    theme
  }).value

  clipboard.write({
    text: input,
    rtf: output
  })
}

Write original string to the clipboard as text and new as RTF


console.log("Create app module");
var learnApp = angular.module('LearnApp', []);

var LearnController = function($scope) {
	var _this = this;
	window.castReceiverManager = cast.receiver.CastReceiverManager.getInstance();
	bus = window.castReceiverManager.getCastMessageBus('urn:x-cast:com.kg.learn');
	window.castReceiverManager.start();

	$scope.sendersCount = 0;

	this.addSender = function(event) {
		$scope.$apply(function() {
			console.log("New sender connected");
			console.log(event);
			$scope.sendersCount++;
			console.log($scope.sendersCount);
		});
	}

	this.removeSender = function(event) {
		$scope.apply(function() {
			console.log("Sender disconnected");
			console.log(event);
			console.log(window.castReceiverManager.getSenders());
			// Close app if there is no more client session
			if (window.castReceiverManager.getSenders().length == 0 &&
				event.reason == cast.receiver.system.DisconnectReason.REQUESTED_BY_SENDER) {
				window.close();
			}
			$scope.sendersCount--;
		});
	};
	window.castReceiverManager.onSenderDisconnected = this.removeSender;
	window.castReceiverManager.onSenderConnected = this.addSender;
};

LearnController.$inject = ['$scope'];
learnApp.controller('LearnController', LearnController);

console.log("Create app module");
var learnApp = angular.module('LearnApp', []);

var LearnController = function($scope) {
	var _this = this;
	window.castReceiverManager = cast.receiver.CastReceiverManager.getInstance();
	bus = window.castReceiverManager.getCastMessageBus('urn:x-cast:com.kg.learn');
	window.castReceiverManager.start();

	$scope.sendersCount = 0;

	this.addSender = function(event) {
		$scope.$apply(function() {
			console.log("New sender connected");
			console.log(event);
			$scope.sendersCount++;
			console.log($scope.sendersCount);
		});
	}

	this.removeSender = function(event) {
		$scope.$apply(function() {
			console.log("Sender disconnected");
			console.log(event);
			console.log(window.castReceiverManager.getSenders());
			// Close app if there is no more client session
			if (window.castReceiverManager.getSenders().length == 0 &&
				event.reason == cast.receiver.system.DisconnectReason.REQUESTED_BY_SENDER) {
				window.close();
			}
			$scope.sendersCount--;
		});
	};
	window.castReceiverManager.onSenderDisconnected = this.removeSender;
	window.castReceiverManager.onSenderConnected = this.addSender;
};

LearnController.$inject = ['$scope'];
learnApp.controller('LearnController', LearnController);

Fix call to on session disconnected


#!/usr/bin/env node

var repl = require('repl');
var protocol = require('../lib/protocol.json');
var Chrome = require('../');

Chrome(function (chrome) {
    var chromeRepl = repl.start({
        'prompt': 'chrome> '
    });

    // disconnect on exit
    chromeRepl.on('exit', function () {
        chrome.close();
    });

    // add protocol API
    for (var domainIdx in protocol.domains) {
        var domainName = protocol.domains[domainIdx].domain;
        chromeRepl.context[domainName] = chrome[domainName];
    }
});

#!/usr/bin/env node

var repl = require('repl');
var protocol = require('../lib/protocol.json');
var Chrome = require('../');

Chrome(function (chrome) {
    var chromeRepl = repl.start({
        'prompt': 'chrome> '
    });

    // disconnect on exit
    chromeRepl.on('exit', function () {
        chrome.close();
    });

    // add protocol API
    for (var domainIdx in protocol.domains) {
        var domainName = protocol.domains[domainIdx].domain;
        chromeRepl.context[domainName] = chrome[domainName];
    }
}).on('error', function () {
    console.error('Cannot connect to Chrome');
});

Add error reporting to the REPL interface


module.exports = function (context) {
  return {
    $: function (expression) {
      return expression
    },

    extend: {
      extendables: {},
      add: function (selector, cssString) {
        this.extendables[selector] = {
          css: cssString,
          selectors: []
        }
      },
      that: function (extendable, selector) {
        if(!this.extendables[extendable]) return false
        this.extendables[extendable]['selectors'].push(selector)
        context.onDone.push(this.extendMaker(extendable))
      },
      extendMaker: function (extendable) {
        var self = this
        return function () {
          return [self.extendables[extendable].selectors].concat(self.extendables[extendable].selectors).join(', ') + ' {' + self.extendables[extendable].css + '}\n'
        }
      }
    }
  }
}

module.exports = function (context) {
  return {
    $: function (expression) {
      return expression
    },

    extend: {
      extendables: {},
      add: function (selector, cssString) {
        this.extendables[selector] = {
          css: cssString,
          selectors: []
        }
      },
      that: function (extendable, selector) {
        if(!this.extendables[extendable]) return false
        this.extendables[extendable]['selectors'].push(selector)
        context.onDone.push(this.extendMaker(extendable))
      },
      extendMaker: function (extendable) {
        var self = this
        return function () {
          var returnVal
          if(!self.extendables[extendable]) return ''
          returnVal = [self.extendables[extendable].selectors].concat(self.extendables[extendable].selectors).join(', ') + ' {' + self.extendables[extendable].css + '}\n'
          self.extendables[extendable] = false
          return returnVal
        }
      }
    }
  }
}

Make extendMake run only once


import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Close from './Close';
import Minimize from './Minimize';
import Resize from './Resize';

var styles = {
  controls: {
    WebkitUserSelect: 'none',
    userSelect: 'none',
    cursor: 'default',
    display: 'flex',
    width: '61px'
  },

  inset: {
    marginLeft: '5px'
  }
};

class Controls extends Component {
  static propTypes = {
    inset: PropTypes.bool,
    isFullscreen: PropTypes.bool,
    onCloseClick: PropTypes.func,
    onMinimizeClick: PropTypes.func,
    onMaximizeClick: PropTypes.func,
    onResizeClick: PropTypes.func
  };

  constructor() {
    super();
    this.state = {
      isOver: false
    };
  }

  render() {
    return (
      <div
        style={{ ...styles.controls }}
        onMouseEnter={() => this.setState({ isOver: true })}
        onMouseLeave={() => this.setState({ isOver: false })}
      >
        <Close onClick={this.props.onCloseClick} showIcon={this.state.isOver} />
        <Minimize
          onClick={this.props.onMinimizeClick}
          showIcon={this.state.isOver}
        />
        <Resize
          isFullscreen={this.props.isFullscreen}
          onClick={this.props.onResizeClick}
          onMaximizeClick={this.props.onMaximizeClick}
          showIcon={this.state.isOver}
        />
      </div>
    );
  }
}

export default Controls;

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Close from './Close';
import Minimize from './Minimize';
import Resize from './Resize';

var styles = {
  controls: {
    WebkitUserSelect: 'none',
    userSelect: 'none',
    cursor: 'default',
    display: 'flex',
    width: '61px'
  },

  inset: {
    marginLeft: '5px'
  }
};

class Controls extends Component {
  static propTypes = {
    inset: PropTypes.bool,
    isFullscreen: PropTypes.bool,
    onCloseClick: PropTypes.func,
    onMinimizeClick: PropTypes.func,
    onMaximizeClick: PropTypes.func,
    onResizeClick: PropTypes.func
  };

  constructor() {
    super();
    this.state = {
      isOver: false
    };
  }

  render() {
    return (
      <div
        style={{ ...styles.controls }}
        onMouseEnter={() => this.setState({ isOver: true })}
        onMouseLeave={() => this.setState({ isOver: false })}
      >
        <Close
          onClick={this.props.onCloseClick}
          showIcon={this.state.isOver}
          isWindowFocused={this.props.isWindowFocused}
        />
        <Minimize
          onClick={this.props.onMinimizeClick}
          showIcon={this.state.isOver}
          isWindowFocused={this.props.isWindowFocused}
        />
        <Resize
          isFullscreen={this.props.isFullscreen}
          onClick={this.props.onResizeClick}
          onMaximizeClick={this.props.onMaximizeClick}
          showIcon={this.state.isOver}
          isWindowFocused={this.props.isWindowFocused}
        />
      </div>
    );
  }
}

export default Controls;

Allow end-user to force `isWindowFocused` prop


import React, { Component } from 'react';
import * as types from '../../../constants/ActionTypes'
import { logout } from '../../../actions/login';
import { connect } from 'react-redux';

class Logout extends Component {

    render() {
        return (
            <li id="logoutButton" onClick={this.props.logout}>
                <a>
                    Logout
                </a>
            </li>
        );
    }
}

export default connect(null, { logout })(Logout)

import React, { Component } from 'react';
import * as types from '../../../constants/ActionTypes'
import { logout } from '../../../actions/login';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';

class Logout extends Component {

    render() {
        return (
            <li id="logoutButton" onClick={this.props.logout}>
                <Link to="/">Logout</Link>
            </li>
        );
    }
}

export default connect(null, { logout })(Logout)

Send user to home when he logs out


import getFeed from './rss-feed-poller';
import loadFile from './config-parser.js';

export default async function rssPoller(robot) {
  try {
    const config = await loadFile(process.env.HUBOT_RSS_CONFIG_FILE || 'hubotrssconfig.json');

    JSON.parse(config).feeds.map(x => getFeed({ ...x, robot }))
      .forEach(x => x.startFeed());
  } catch (err) {
    robot.logger.debug(err.message);
  }
}

import getFeed from './rss-feed-poller';
import loadFile from './config-parser.js';

export default async function rssPoller(robot) {
  try {
    const config = await loadFile(process.env.HUBOT_RSS_CONFIG_FILE || 'hubotrssconfig.json');

    if (!process.env.HUBOT_RSS_FEED_DISABLE) {
      JSON.parse(config).feeds.map(x => getFeed({ ...x, robot }))
        .forEach(x => x.startFeed());
    }
  } catch (err) {
    robot.logger.debug(err.message);
  }
}

Add env variable to disable this plugin


/* global require, module */
var EmberAddon = require('ember-cli/lib/broccoli/ember-addon')

module.exports = function (defaults) {
  var app = new EmberAddon(defaults, {

    babel: {
      optional: ['es7.decorators']
    },
    codemirror: {
      modes: ['javascript', 'handlebars', 'markdown'],
      themes: ['mdn-like']
    },
    'ember-cli-mocha': {
      useLintTree: false
    },
    'ember-prism': {
      components: ['javascript'],
      theme: 'coy'
    },
    sassOptions: {
      includePaths: [
      ]
    }
  })

  app.import('bower_components/sinonjs/sinon.js')

  /*
    This build file specifes the options for the dummy test app of this
    addon, located in `/tests/dummy`
    This build file does *not* influence how the addon or the app using it
    behave. You most likely want to be modifying `./index.js` or app's build file
  */

  return app.toTree()
}

/* global require, module */
var EmberAddon = require('ember-cli/lib/broccoli/ember-addon')

module.exports = function (defaults) {
  var app = new EmberAddon(defaults, {

    babel: {
      includePolyfill: true,
      optional: ['es7.decorators']
    },
    codemirror: {
      modes: ['javascript', 'handlebars', 'markdown'],
      themes: ['mdn-like']
    },
    'ember-cli-mocha': {
      useLintTree: false
    },
    'ember-prism': {
      components: ['javascript'],
      theme: 'coy'
    },
    sassOptions: {
      includePaths: [
      ]
    }
  })

  app.import('bower_components/sinonjs/sinon.js')

  /*
    This build file specifes the options for the dummy test app of this
    addon, located in `/tests/dummy`
    This build file does *not* influence how the addon or the app using it
    behave. You most likely want to be modifying `./index.js` or app's build file
  */

  return app.toTree()
}

Include babel polyfill for github pages demo


// Mixins
let i18nMixin =require('../../../../common/i18n').mixin;
let searchBehaviour = require('../../common/search-mixin').mixin;
var searchWrappedAction = require('../action-wrapper');

module.exports = {
    mixins: [i18nMixin, searchBehaviour],
    getInitialState(){
      return {
        isLoading: false
      }
    },
    componentWillMount(){
      this._prepareSearch = searchWrappedAction(this.search, this);
    }
};

// Mixins
let i18nMixin =require('../../../../common/i18n').mixin;
let searchBehaviour = require('../../common/search-mixin').mixin;
var searchWrappedAction = require('../action-wrapper');
let SearchBar = require('../../../../search/search-bar').component;
var React = require('react');

module.exports = {
    mixins: [i18nMixin, searchBehaviour],
    getInitialState(){
      return {
        isLoading: false
      }
    },
    _runSearch(){
      var criteria = this.refs.searchBar.getValue();
      return this.props.searchAction(this._buildSearchCriteria(criteria.scope, criteria.query))
    },
    _SearchBarComponent(){
      return <SearchBar
                ref='searchBar'
                value={this.props.query}
                scope={this.props.scope}
                scopes={this.props.scopeList}
                loading={this.state.isLoadingSearch}
                handleChange={this._runSearch}
              />;
    },
    componentWillMount(){
      this._prepareSearch = searchWrappedAction(this._runSearch, this);
    }
};

Rewrite mixin in order to call runSearhc.


/**
 * main.js
 *
 * Only runs in modern browsers via feature detection
 */

if('querySelector' in document && 'localStorage' in window && 'addEventListener' in window) {

}

/**
 * main.js
 *
 * Only runs in modern browsers via feature detection
 */

if('querySelector' in document && 'localStorage' in window && 'addEventListener' in window) {

  // Add class "js" to html element
  document.querySelector('html').classList.add('js');

}

Add class "js" to html element


Template.postsList.helpers({
  posts: function() {
    return Posts.find();
  }
});

Template.postsList.helpers({
  posts: function() {
    return Posts.find({}, {sort: {submitted: -1}});
  }
});

Sort posts by submitted timestamp.


'use strict';

var React = require('react');
var ReactDOM = require('react-dom');
var GraphPanel = require('./GraphPanel.js');
var SearchPanel = require('./SearchPanel.js');
var NodeInfoPanel = require('./NodeInfoPanel.js');

var Graphalyzer = React.createClass({
  render: function() {
    return (
      <div>
        <GraphPanel />
        <SearchPanel />
        <NodeInfoPanel />
      </div>
    );
  }
});

ReactDOM.render(
  <Graphalyzer />,
  document.getElementById('main')
);

'use strict';

var React = require('react');
var ReactDOM = require('react-dom');
var GraphPanel = require('./GraphPanel.js');
var SearchPanel = require('./SearchPanel.js');
var NodeInfoPanel = require('./NodeInfoPanel.js');

var Graphalyzer = React.createClass({
  getDefaultProps: function() {
    return {
      websocket: new WebSocket("ws://rwhite226.duckdns.org:1618/ws")
    };
  },

  getInitialState: function() {
    return {
      graphData: {},
      selectedNode: {}
    };
  },

  componentDidMount: function() {
    this.websocket.onmessage = handleWSMessage;
  },

  handleWSMessage: function(event) {
    var response = event.data;
    if (response !== null) {
      this.setState({graphData: response});
    }
  },

  render: function() {
    return (
      <div>
        <GraphPanel />
        <SearchPanel
          websocket = {this.props.websocket}
        />
        <NodeInfoPanel />
      </div>
    );
  }
});

ReactDOM.render(
  <Graphalyzer />,
  document.getElementById('main')
);

Add WebSocket to main Graphalyzer component


import path from 'path';
import merge from 'webpack-merge';
import CleanWebpackPlugin from 'clean-webpack-plugin';

import CommonConfig from './webpack.common';

let config = {
  entry: ['./src/main.js'],
  output: {
    filename: 'main.bundle.js',
    path: path.resolve(__dirname, 'src', '.build'),
  },
  node: {
    __dirname: true,
  },
  target: 'electron-main',
  plugins: [
    new CleanWebpackPlugin(['src/.build/main.bundle.js']),
  ],
};

if (process.env.NODE_ENV === 'development') {
  config = merge(config, {
    devtool: 'inline-cheap-source-map',
  });
} else {
  config = merge(config, {
    node: {
      __dirname: false,
    },
  });
}

export default merge(CommonConfig, config);

import path from 'path';
import merge from 'webpack-merge';
import CleanWebpackPlugin from 'clean-webpack-plugin';

import CommonConfig from './webpack.common';

let config = {
  entry: ['./src/main.js'],
  output: {
    filename: 'main.bundle.js',
    path: path.resolve(__dirname, 'src', '.build'),
  },
  node: {
    __dirname: true,
  },
  target: 'electron-main',
  plugins: [
    new CleanWebpackPlugin(['src/.build/main.bundle.js']),
  ],
};

if (process.env.NODE_ENV === 'development') {
  config = merge(config, {
    devtool: 'inline-source-map',
  });
} else {
  config = merge(config, {
    node: {
      __dirname: false,
    },
  });
}

export default merge(CommonConfig, config);

Use original source for debugging main process


/** @babel */

import { CompositeDisposable, Disposable } from 'atom'

export default class MarkerManager extends Disposable {
  disposables = new CompositeDisposable()

  constructor (editor) {
    super(() => this.disposables.dispose())

    this.editor = editor
    this.markers = []

    this.disposables.add(latex.log.onMessages((messages, reset) => this.addMarkers(messages, reset)))
    this.disposables.add(new Disposable(() => this.clear()))
    this.disposables.add(this.editor.onDidDestroy(() => this.dispose()))

    this.addMarkers(latex.log.getMessages())
  }

  addMarkers (messages, reset) {
    const filePath = this.editor.getPath()

    if (reset) this.clear()

    if (filePath) {
      for (const message of messages) {
        if (message.filePath && message.range && filePath.includes(message.filePath)) {
          this.addMarker(message)
        }
      }
    }
  }

  addMarker (message) {
    const marker = this.editor.markBufferRange(message.range, { invalidate: 'touch' })
    this.editor.decorateMarker(marker, { type: 'line-number', class: `latex-${message.type}` })
    this.markers.push(marker)
  }

  clear () {
    for (const marker of this.markers) {
      marker.destroy()
    }
    this.markers = []
  }
}

/** @babel */

import { CompositeDisposable, Disposable } from 'atom'

export default class MarkerManager extends Disposable {
  disposables = new CompositeDisposable()

  constructor (editor) {
    super(() => this.disposables.dispose())

    this.editor = editor
    this.markers = []

    this.disposables.add(latex.log.onMessages((messages, reset) => this.addMarkers(messages, reset)))
    this.disposables.add(new Disposable(() => this.clear()))
    this.disposables.add(this.editor.onDidDestroy(() => this.dispose()))
    this.disposables.add(atom.config.onDidChange('latex.loggingLevel', () => this.update()))

    this.addMarkers(latex.log.getMessages())
  }

  update () {
    this.clear()
    this.addMarkers(latex.log.getMessages())
  }

  addMarkers (messages, reset) {
    if (reset) this.clear()

    if (this.editor.getPath()) {
      for (const message of messages) {
        this.addMarker(message.type, message.filePath, message.range)
        this.addMarker(message.type, message.logPath, message.logRange)
      }
    }
  }

  addMarker (type, filePath, range) {
    const currentFilePath = this.editor.getPath()
    if (filePath && range && currentFilePath.includes(filePath)) {
      const marker = this.editor.markBufferRange(range, { invalidate: 'touch' })
      this.editor.decorateMarker(marker, { type: 'line-number', class: `latex-${type}` })
      this.markers.push(marker)
    }
  }

  clear () {
    for (const marker of this.markers) {
      marker.destroy()
    }
    this.markers = []
  }
}

Add markers in log files


fs = require('fs');

module.exports = {
    publicClasses: function(context, options) {
        'use strict';
        var ret = "";

        for(var i=0; i < context.length; i++) {
            if(!context[i].itemtype && context[i].access === 'public') {
                ret = ret + options.fn(context[i]);
            } else if (context[i].itemtype) {
                ret = ret + options.fn(context[i]);
            }
        }

        return ret;
    },
    search : function(classes, modules) {
        'use strict';
        var ret = '';

        for(var i=0; i < classes.length; i++) {
            if(i > 0) {
                ret += ', ';
            }
            ret += "\"" + 'classes/' + classes[i].displayName + "\"";
        }

        if(ret.length > 0 && modules.length > 0) {
            ret += ', ';
        }

        for(var j=0; j < modules.length; j++) {
            if(j > 0) {
                ret += ', ';
            }
            ret += "\"" + 'modules/' + modules[j].displayName + "\"";
        }

        return ret;
    }
};

var fs, path, markdown;
fs = require('fs');
path = require("path");
markdown = require( "markdown" ).markdown;

module.exports = {
    publicClasses: function(context, options) {
        'use strict';
        var ret = "";

        for(var i=0; i < context.length; i++) {
            if(!context[i].itemtype && context[i].access === 'public') {
                ret = ret + options.fn(context[i]);
            } else if (context[i].itemtype) {
                ret = ret + options.fn(context[i]);
            }
        }

        return ret;
    },
    search : function(classes, modules) {
        'use strict';
        var ret = '';

        for(var i=0; i < classes.length; i++) {
            if(i > 0) {
                ret += ', ';
            }
            ret += "\"" + 'classes/' + classes[i].displayName + "\"";
        }

        if(ret.length > 0 && modules.length > 0) {
            ret += ', ';
        }

        for(var j=0; j < modules.length; j++) {
            if(j > 0) {
                ret += ', ';
            }
            ret += "\"" + 'modules/' + modules[j].displayName + "\"";
        }

        return ret;
    },
    homeContent : function () {
        var config = path.join(process.cwd(), 'yuidoc');
        if (fs.existsSync(config + '.json') === true) {
            config = require(config);
        }

        var content = config.theme.home
        if (typeof content === 'string' && content !== '') {
            content = path.join(process.cwd(), content);
        } else {
            content = path.join(process.cwd(), 'README.md');
        }

        if (fs.existsSync(content) === true) {
            content = fs.readFileSync(content, {encoding: "utf8"});
            content = markdown.toHTML(content);
        } else {
            content = '';
        }
        return content;
    }
};

Add helper for home page content


/* @flow */

const MODULE_EXTRACTION_REGEX = /^(\w[^\/\\]+)/

export function extractModuleName(moduleName: string): ?string {
  if (moduleName.indexOf(' ') !== -1) {
    return null
  }

  const matches = MODULE_EXTRACTION_REGEX.exec(moduleName)
  if (matches) {
    return matches[1]
  }
  return null
}

export function getRootDirectory(): string {
  // TODO: Make this actually work
  // NOTE: `npm-install-webpack-plugin` does the same by the way
  return process.cwd()
}

export function getModuleName(moduleName: string, loader: boolean): string {
  if (loader && !moduleName.match(/\-loader$/)) {
    moduleName += '-loader'
  }
  return moduleName
}

export function isBuiltin(moduleName: string): boolean {
  try {
    return require.resolve(moduleName) === moduleName
  } catch (_) {
    return false
  }
}

/* @flow */

const MODULE_EXTRACTION_REGEX = /^(\w[^\/\\]+)/

export function extractModuleName(moduleName: string): ?string {
  if (moduleName.indexOf(' ') !== -1) {
    return null
  }

  const matches = MODULE_EXTRACTION_REGEX.exec(moduleName)
  if (matches) {
    return matches[1]
  }
  return null
}

export function getRootDirectory(compiler: Object): string {
  const options = compiler.options
  const rootDirectory = options.resolve && options.resolve.root
  if (rootDirectory) {
    return Array.isArray(rootDirectory) ? rootDirectory[0] : rootDirectory
  }
  return process.cwd()
}

export function getModuleName(moduleName: string, loader: boolean): string {
  if (loader && !moduleName.match(/\-loader$/)) {
    moduleName += '-loader'
  }
  return moduleName
}

export function isBuiltin(moduleName: string): boolean {
  try {
    return require.resolve(moduleName) === moduleName
  } catch (_) {
    return false
  }
}

Add resolve.root support to getRootDirectory helper in motion-webpack-npm


'use strict'

var apiKeys = {
  newsApiKey: '',
  twitter_consumer_key: '',
  twitter_consumer_secret: '',
  twitter_bearer_token: ''
}

module.exports = apiKeys

'use strict'

var apiKeys = {
  newsApiKey: '',
  twitter_consumer_key: '',
  twitter_consumer_secret: '',
  twitter_access_token_key: '',
  twitter_access_token_secret: '',
  twitter_bearer_token: ''
}

module.exports = apiKeys

Add Twitter user API keys


import statusIcon from '../mr_widget_status_icon';

export default {
  name: 'MRWidgetConflicts',
  props: {
    mr: { type: Object, required: true },
  },
  components: {
    statusIcon,
  },
  template: `

      <status-icon
        status="failed"
        showDisabledButton />

          Fast-forward merge is not possible.
          To merge this request, first rebase locally

        <template v-else>

            There are merge conflicts.

              Resolve these conflicts or ask someone with write access to this repository to merge it locally

            Resolve conflicts

            Merge locally

        </template>

  `,
};

import statusIcon from '../mr_widget_status_icon';

export default {
  name: 'MRWidgetConflicts',
  props: {
    mr: { type: Object, required: true },
  },
  components: {
    statusIcon,
  },
  template: `

      <status-icon
        status="failed"
        showDisabledButton />

          Fast-forward merge is not possible.
          To merge this request, first rebase locally.

        <template v-else>

            There are merge conflicts.

              Resolve these conflicts or ask someone with write access to this repository to merge it locally

            Resolve conflicts

            Merge locally

        </template>

  `,
};

Add period to multi-sentence rebase locally message


/*
 Toast notification popup jQuery plugin
 (c) 2016 Nupin Mathew <nupindev@gmail.com>
 License: MIT
*/
$(function () {
    /*Method to show a toast notification like popup with a message which will be closed after a fixed time*/
    $.fn.showToast = function (options) {
        var defaults = {
            message: 'This is a toast notification!',
            timeout: 1500
        };
        var settings = $.extend({}, defaults, options);
        var self = this;
        var margin = 100;
        $(self).css("width", "auto");
        $(self).text(settings.message);
        var windowWidth = window.innerWidth;
        var toastWidth = $(self).innerWidth() + margin;
        if (toastWidth >= windowWidth) {
            toastWidth = windowWidth - margin;
            $(self).css("width", toastWidth);
        }
        else {
            toastWidth = $(self).innerWidth();
        }
        var left = (windowWidth - toastWidth) / 2.0;
        var leftInPercentage = left * 100 / windowWidth;
        $(self).css("left", leftInPercentage + "%");
        $(self).fadeIn(400);
        $(self).removeClass("success warning error");
        if (settings.mode == "success") {
            $(self).addClass('success');
        } else if (settings.mode == "warning") {
            $(self).addClass('warning');
        } else if (settings.mode == "error") {
            $(self).addClass('error');
        }
        setTimeout(function () {
            $(self).fadeOut(600);
        }, settings.timeout);
    };
});

/*
 Toast notification popup jQuery plugin
 (c) 2016 Nupin Mathew <nupindev@gmail.com>
 License: MIT
*/
$(function () {
    /*Method to show a toast notification like popup with a message which will be closed after a fixed time*/
    $.fn.showToast = function (options) {
        var defaults = {
            message: 'This is a toast notification!',
            timeout: 1500,
            mode: 'info'
        };
        var settings = $.extend({}, defaults, options);
        var self = this;
        var margin = 100;
        $(self).css("width", "auto");
        $(self).text(settings.message);
        var windowWidth = window.innerWidth;
        var toastWidth = $(self).innerWidth() + margin;
        if (toastWidth >= windowWidth) {
            toastWidth = windowWidth - margin;
            $(self).css("width", toastWidth);
        }
        else {
            toastWidth = $(self).innerWidth();
        }
        var left = (windowWidth - toastWidth) / 2.0;
        var leftInPercentage = left * 100 / windowWidth;
        $(self).css("left", leftInPercentage + "%");
        $(self).fadeIn(400);
        $(self).removeClass("success warning error");
        if (settings.mode == "success") {
            $(self).addClass('success');
        } else if (settings.mode == "warning") {
            $(self).addClass('warning');
        } else if (settings.mode == "error") {
            $(self).addClass('error');
        }
        setTimeout(function () {
            $(self).fadeOut(600);
        }, settings.timeout);
    };
});

Update default value of mode


(function (module) {
    module.controller("SamplesController", SamplesController);
    SamplesController.$inject = ["$state", "project", "$filter", "samples", "processTemplates"];

    function SamplesController($state, project, $filter, samples, processTemplates) {
        var ctrl = this;

        ctrl.project = project;
        ctrl.viewSample = viewSample;
        ctrl.samples = samples;
        ctrl.createSample = createSample;

        if (ctrl.samples.length !== 0) {
            var sortedSamples = $filter('orderBy')(ctrl.samples, 'name');
            ctrl.current = sortedSamples[0];
            $state.go('projects.project.samples.list.edit', {sample_id: ctrl.current.id});
        }

        //////////////////

        function viewSample(sample) {
            ctrl.current = sample;
            $state.go('projects.project.samples.list.edit', {sample_id: ctrl.current.id});
        }

        function createSample() {
            var template = processTemplates.getTemplateByName('As Received');
            processTemplates.setActiveTemplate(template);
            $state.go('projects.project.processes.create');
        }
    }
}(angular.module('materialscommons')));

(function (module) {
    module.controller("SamplesController", SamplesController);
    SamplesController.$inject = ["$state", "project", "$filter", "samples"];

    function SamplesController($state, project, $filter, samples) {
        var ctrl = this;

        ctrl.project = project;
        ctrl.viewSample = viewSample;
        ctrl.samples = samples;
        ctrl.createSample = createSample;

        if (ctrl.samples.length !== 0) {
            var sortedSamples = $filter('orderBy')(ctrl.samples, 'name');
            ctrl.current = sortedSamples[0];
            $state.go('projects.project.samples.list.edit', {sample_id: ctrl.current.id});
        }

        //////////////////

        function viewSample(sample) {
            ctrl.current = sample;
            $state.go('projects.project.samples.list.edit', {sample_id: ctrl.current.id});
        }

        function createSample() {
            $state.go('projects.project.processes.create', {process: 'As Received', process_id: ''});
        }
    }
}(angular.module('materialscommons')));

Create sample using new process create method.


const router = require('express').Router()

const { getProjectDetails } = require('./shared.middleware')

const {
  populateDetailsFormMiddleware,
  investmentDetailsFormPostMiddleware,
} = require('./form.middleware')

function createGetHandler (req, res) {
  if (!res.locals.equityCompany) {
    return res.redirect('/investment/start')
  }
  return res.render('investment/create', {
    title: 'Add investment project',
  })
}

function createPostHandler (req, res) {
  if (res.locals.form.errors) {
    return res.render('investment/create')
  }
  return res.redirect(`/investment/${res.locals.resultId}`, {
    title: 'Add investment project',
  })
}

router.param('id', getProjectDetails)
router.get('/create', populateDetailsFormMiddleware, createGetHandler)
router.post('/create', populateDetailsFormMiddleware, investmentDetailsFormPostMiddleware, createPostHandler)

module.exports = {
  router,
  createGetHandler,
  createPostHandler,
}

const router = require('express').Router()

const { getProjectDetails } = require('./shared.middleware')

const {
  populateDetailsFormMiddleware,
  investmentDetailsFormPostMiddleware,
} = require('./form.middleware')

function createGetHandler (req, res) {
  if (!res.locals.equityCompany) {
    return res.redirect('/investment/start')
  }
  return res.render('investment/create', {
    title: 'Add investment project',
  })
}

function createPostHandler (req, res) {
  if (res.locals.form.errors) {
    return res.render('investment/create', {
      title: 'Add investment project',
    })
  }
  return res.redirect(`/investment/${res.locals.resultId}`)
}

router.param('id', getProjectDetails)
router.get('/create', populateDetailsFormMiddleware, createGetHandler)
router.post('/create', populateDetailsFormMiddleware, investmentDetailsFormPostMiddleware, createPostHandler)

module.exports = {
  router,
  createGetHandler,
  createPostHandler,
}

Fix error with data being passed to redirect method


var fs = require('fs');
var path = require('path');
var css = require('css');

module.exports = CssFile;

function CssFile(dir) {
  this.path = path.resolve(dir);

  var content = fs.readFileSync(this.path).toString();
  var size = content.match(/\n/g).length;
  this.css = css.parse(content);
  this.rules = this.css.stylesheet.rules;
  this.result = new Array(size);
  for (i = 0; i < size; i++) {
    this.result[i] = null;
  }
}

CssFile.prototype.mark = function(val, start, end) {
  for (i = start - 1; i < end; i++) {
    this.result[i] += val;
  }
};

var fs = require('fs');
var path = require('path');
var css = require('css');

module.exports = CssFile;

function CssFile(dir) {
  this.path = path.resolve(dir);

  var content = fs.readFileSync(this.path).toString();
  var size = content.match(/\n/g).length;
  this.css = css.parse(content);
  this.rules = this.css.stylesheet.rules;
  this.result = new Array(size);
  for (var i = 0; i < size; i++) {
    this.result[i] = null;
  }
}

CssFile.prototype.mark = function(val, start, end) {
  for (var i = start - 1; i < end; i++) {
    this.result[i] += val;
  }
};

Fix '"i" is not defined'


/* jshint ignore:start */

try {
  var metaName = prefix + '/config/environment';
  var rawConfig = Ember['default'].$('meta[name="' + metaName + '"]').attr('content');
  var config = JSON.parse(unescape(rawConfig));

  var exports = { 'default': config };

  Object.defineProperty(exports, '__esModule', { value: true });

  return exports;
}
catch(err) {
  throw new Error('Could not read config from meta tag with name "' + metaName + '".');
}

/* jshint ignore:end */

/* jshint ignore:start */

try {
  var metaName = prefix + '/config/environment';
  var rawConfig = document.querySelector('meta[name="' + metaName + '"]').getAttribute('content');
  var config = JSON.parse(unescape(rawConfig));

  var exports = { 'default': config };

  Object.defineProperty(exports, '__esModule', { value: true });

  return exports;
}
catch(err) {
  throw new Error('Could not read config from meta tag with name "' + metaName + '".');
}

/* jshint ignore:end */

Remove jQuery usage to read meta config.


import Ember from 'ember';

export default Ember.Component.extend({
  aviaryApiClient: null, // injected
  classNames: ['edit-icon'],
  image: null,
  url: null,
  imageSelector: null,
  closeOnSave: false,

  imageToEdit: function() {
    var imageNotSet = Ember.isEmpty(this.get('image'));
    var selector = this.get('imageSelector');
    return imageNotSet ? this.get('parentView').$(selector || 'img') : this.get('image');
  }.property('parentView', 'image', 'imageSelector'),

  click: function() {
    var self = this;
    var options = {
      image: this.get('imageToEdit'),
      url: this.get('url'),
      onSave: function(imageId, src) {
        self.send('onSave', imageId, src);
      }
    };

    this.aviaryApiClient.launch(options);

    return false;
  },

  actions: {
    onSave: function(imageId, src) {
      this.sendAction('onSave', imageId, src);

      var closeOnSave = this.get('closeOnSave');
      var featherEditor = this.aviaryApiClient.get('featherEditor');
      if(closeOnSave) { featherEditor.close(); }
    }
  }
});

import Ember from 'ember';

export default Ember.Component.extend({
  aviaryApiClient: null, // injected
  classNames: ['edit-icon'],
  classNameBindings: ['featherActive:active'],
  image: null,
  url: null,
  imageSelector: null,
  closeOnSave: false,
  featherActive: false,

  imageToEdit: function() {
    var imageNotSet = Ember.isEmpty(this.get('image'));
    var selector = this.get('imageSelector');
    return imageNotSet ? this.get('parentView').$(selector || 'img') : this.get('image');
  }.property('parentView', 'image', 'imageSelector'),

  click: function() {
    var self = this;
    var options = {
      image: this.get('imageToEdit'),
      url: this.get('url'),
      onSave: function(imageId, src) {
        self.send('onSave', imageId, src);
      },
      onClose: function() {
        self.send('onClose');
      }
    };

    this.aviaryApiClient.launch(options);
    this.set('featherActive', true);

    return false;
  },

  actions: {
    onSave: function(imageId, src) {
      this.sendAction('onSave', imageId, src);

      var closeOnSave = this.get('closeOnSave');
      var featherEditor = this.aviaryApiClient.get('featherEditor');
      if(closeOnSave) { featherEditor.close(); }
    },
    onClose: function() {
      this.set('featherActive', false);
    }
  }
});

Add 'active' class bindings for component that is added when Aviary Editor is launched and removed with Aviary's 'onClose' callback


// Check mobile platform

$(document).ready(function () {
    if (Framework7.prototype.device.ios) {
        // Redirect to iOS page
        var iosPaneUrl = new URI('MobilePane-ios.html').absoluteTo(window.location).toString();
        window.location.href = iosPaneUrl;
    } else if (Framework7.prototype.device.android) {
        $('#message').text('Android is not yet supported.');
    } else {
        $('#message').text('YOU SHOULD NOT BE HERE');
    }

    insertData('diag', 'User agent', window.navigator.userAgent);
    insertData('diag', 'iOS', Framework7.prototype.device.ios);
    insertData('diag', 'iPad', Framework7.prototype.device.ipad);
    insertData('diag', 'iPhone', Framework7.prototype.device.iphone);
    insertData('diag', 'Android', Framework7.prototype.device.android);
});

function insertData(id, headerText, valueText) {
    var pane = $("#" + id);

    var lf = $(document.createElement("br"));

    var header = $(document.createElement("span"));
    header.text(headerText + ': ');

    var value = $(document.createElement("span"));
    value.text(valueText);

    pane.append(header);
    pane.append(value);
    pane.append(lf);
}

// Check mobile platform

$(document).ready(function () {
    // Temporary hack for oddball Outlook for iOS user agent
    var ios = window.navigator.userAgent.match(/(Outlook-iOS)/);
    if (ios) Framework7.prototype.device.ios = true;
    if (Framework7.prototype.device.ios) {
        // Redirect to iOS page
        var iosPaneUrl = new URI('MobilePane-ios.html').absoluteTo(window.location).toString();
        window.location.href = iosPaneUrl;
    } else if (Framework7.prototype.device.android) {
        $('#message').text('Android is not yet supported.');
    } else {
        $('#message').text('YOU SHOULD NOT BE HERE');
    }

    insertData('diag', 'User agent', window.navigator.userAgent);
    insertData('diag', 'iOS', Framework7.prototype.device.ios);
    insertData('diag', 'iPad', Framework7.prototype.device.ipad);
    insertData('diag', 'iPhone', Framework7.prototype.device.iphone);
    insertData('diag', 'Android', Framework7.prototype.device.android);
});

function insertData(id, headerText, valueText) {
    var pane = $("#" + id);

    var lf = $(document.createElement("br"));

    var header = $(document.createElement("span"));
    header.text(headerText + ': ');

    var value = $(document.createElement("span"));
    value.text(valueText);

    pane.append(header);
    pane.append(value);
    pane.append(lf);
}

Add temporary fix for odd outlook for ios user agent


export const colors = {
  NEUTRAL_LIGHTEST: '#fff',
  NEUTRAL_LIGHT: '#f7f7fa',
  NEUTRAL: '#e4e4e6',
  NEUTRAL_DARK: '#c0c0c4',
  NEUTRAL_DARKEST: '#82828c',
  TEAL_LIGHTEST: '#e1ecfa',
  TEAL_LIGHT: '#c1cede',
  TEAL: '#64788f',
  TEAL_DARK: '#344b63',
  TEAL_DARKEST: '#2a3b4d',
};

export const colors = {
  NEUTRAL_LIGHTEST: '#fff',
  NEUTRAL_LIGHT: '#f7f7fa',
  NEUTRAL: '#e4e4e6',
  NEUTRAL_DARK: '#c0c0c4',
  NEUTRAL_DARKEST: '#82828c',
  RUBY_DARK: '#e84b17',
  TEAL_LIGHTEST: '#e1ecfa',
  TEAL_LIGHT: '#c1cede',
  TEAL: '#64788f',
  TEAL_DARK: '#344b63',
  TEAL_DARKEST: '#2a3b4d',
};

Add our ruby dark color to the colors constant


const path = require('path')

module.exports = function nuxtBootstrapVue (moduleOtions) {
  // Conditionally require bootstrap original css too if not explicitly disabled
  if (moduleOtions.css !== false) {
    this.options.css.unshift('bootstrap/dist/css/bootstrap.css')
  }

  // Register plugin
  this.addPlugin({ src: path.resolve(__dirname, 'plugin.js'), options })

  // Add library styles
  this.options.css.push('bootstrap-vue/dist/bootstrap-vue.css')
}

module.exports.meta = require('./package.json')

const path = require('path')

module.exports = function nuxtBootstrapVue (moduleOptions) {
  // Conditionally require bootstrap original css too if not explicitly disabled
  if (moduleOptions.css !== false) {
    this.options.css.unshift('bootstrap/dist/css/bootstrap.css')
  }

  // Register plugin
  this.addPlugin({ src: path.resolve(__dirname, 'plugin.js'), moduleOptions })

  // Add library styles
  this.options.css.push('bootstrap-vue/dist/bootstrap-vue.css')
}

module.exports.meta = require('./package.json')

Fix options reference and moduleOptions typo


// 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
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require js/jquery.autotab.js
//= require js/foundation.min
//= require js/foundation/foundation.offcanvas
//= require_tree .
$( document ).ready(function() {
  $(document).foundation()
});
$(document).ready(function() {
  $('#pick_number1').autotab({ target: '#pick_number2', format: 'numeric' });
    $('#pick_number2').autotab({ target: '#pick_number3', format: 'numeric'});
     $('#pick_number3').autotab({ target: '#pick_number4', format: 'numeric'});
      $('#pick_number4').autotab({ target: '#pick_number5', format: 'numeric'});
       $('#pick_number5').autotab({ target: '#pick_number6', format: 'numeric'});
});

// 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
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require js/jquery.autotab.js
//= require js/foundation.min
//= require js/foundation/foundation.offcanvas
//= require_tree .
$( document ).ready(function() {
  $(document).foundation()
});
$(document).on("ready page:load", function(){
  $('#pick_number1').autotab({ target: '#pick_number2', format: 'numeric' });
    $('#pick_number2').autotab({ target: '#pick_number3', format: 'numeric'});
     $('#pick_number3').autotab({ target: '#pick_number4', format: 'numeric'});
      $('#pick_number4').autotab({ target: '#pick_number5', format: 'numeric'});
       $('#pick_number5').autotab({ target: '#pick_number6', format: 'numeric'});
});

Add autocomplete on page load


$(document).ready(function() {
  // setup html editor
  var imgUploadHtml = $('#html-editor-image-upload-tab').html();

  if (imgUploadHtml) {
    var options = {
        "html": true,
      customTemplates: {
        image: function(locale) {
          return imgUploadHtml;
        }
      }
    };
    $('textarea.html-editor').wysihtml5(options);
  } else {
    $("textarea.html-editor").each(function(){$(this).wysihtml5();});
  }
});

$(document).ready(function() {
  // setup html editor
  var imgUploadHtml = $('#html-editor-image-upload-tab').html();
  var handler;

  if (imgUploadHtml) {
    var options = {
        "html": true,
      customTemplates: {
        image: function(locale) {
          return imgUploadHtml;
        }
      }
    };
    handler = function() { $(this).wysihtml5(options); };
  } else {
    handler = function() { $(this).wysihtml5(); };
  }
  $('textarea.html-editor').each(handler);
  $(document).on('DOMNodeInserted', function(e) {
      $('textarea.html-editor', e.target).each(handler);
  })
});

Make the HTML Editor component monitor every node insertion for HTML WYSIWYG widgets. This is so that we can insert new editors at runtime and they will automatically be enabled.


$(document).ready(function() {
  $("a.load_reviews").on("click", function(e){
//Send AJAX LOW-LEVEL get request
  $.ajax({
    method: "GET",
    url: this.href
  }).done(function(response) {
//get response
    $("div.reviews").html(response)
//Load data into html
  });
  e.preventDefault();
  })
})

$(document).ready(function() {
  $("a.load_reviews").on("click", function(e){
//Send AJAX HIGH-LEVEL get request
  $.get(this.href).success(function(json) {
    var $li = $("div.reviews li")
    $li.html(" ")
    json.forEach(function(review) {
      $li.append("<li>" + review + "</li>");
    });
  });
 //Load response into HTML of page
  e.preventDefault();
 });
});

Send AJAX HIGH-LEVEL get request


/* jshint node: true */

var mergeTrees = require('broccoli-merge-trees');
var pickFiles = require('broccoli-static-compiler');
var compileES6 = require('broccoli-es6-concatenator');
var templateCompiler = require('broccoli-ember-hbs-template-compiler');
var registry = require('./registry');
var wrap = require('./wrap');
var version = require('../package.json').version;

var appTree = pickFiles('../app-addon', { srcDir: '/', destDir: 'app-addon'});

var templateTree = templateCompiler('../app-addon/templates', { module: true });
templateTree = pickFiles(templateTree, {srcDir: '/', destDir: 'app-addon/templates'});

var vendorTree = mergeTrees(['../vendor-addon', '../vendor']);
vendorTree = pickFiles(vendorTree, { srcDir: '/', destDir: 'vendor' });

var precompiled = mergeTrees([vendorTree, appTree, templateTree]);
var registrations = registry(pickFiles(precompiled, {srcDir: '/app-addon', destDir: '/'}));

var compiled = compileES6(mergeTrees(['.', mergeTrees([precompiled, registrations])]), {
  loaderFile: 'vendor/loader/loader.js',
  inputFiles: ['vendor/liquid-fire.js', 'app-addon/**/*.js'],
  ignoredModules: ['ember'],
  outputFile: '/liquid-fire-' + version + '.js',
  legacyFilesToAppend: ['registry-output.js', 'glue.js']
});

module.exports = wrap(compiled);

/* jshint node: true */

var mergeTrees = require('broccoli-merge-trees');
var pickFiles = require('broccoli-static-compiler');
var compileES6 = require('broccoli-es6-concatenator');
var templateCompiler = require('broccoli-ember-hbs-template-compiler');
var registry = require('./registry');
var wrap = require('./wrap');
var version = require('../package.json').version;

var appTree = pickFiles('../app-addon', { srcDir: '/', destDir: 'app-addon'});

var templateTree = templateCompiler('../app-addon/templates', { module: true });
templateTree = pickFiles(templateTree, {srcDir: '/', destDir: 'app-addon/templates'});

var vendorTree = mergeTrees(['../vendor-addon', '../vendor']);
vendorTree = pickFiles(vendorTree, { srcDir: '/', destDir: 'vendor' });

var precompiled = mergeTrees([vendorTree, appTree, templateTree]);
var registrations = registry(pickFiles(precompiled, {srcDir: '/app-addon', destDir: '/'}));

var compiled = compileES6(mergeTrees(['.', mergeTrees([precompiled, registrations])]), {
  wrapInEval: false,
  loaderFile: 'vendor/loader/loader.js',
  inputFiles: ['vendor/liquid-fire.js', 'app-addon/**/*.js'],
  ignoredModules: ['ember'],
  outputFile: '/liquid-fire-' + version + '.js',
  legacyFilesToAppend: ['registry-output.js', 'glue.js']
});

module.exports = wrap(compiled);

Disable wrapInEval for standalone builds.


$( document ).on('DOMNodeInserted', 'pre', function(eventObject) {
	var thisElement = $(this);

	if(!thisElement.hasClass('language-abap')) {
		changingPres = true;

		thisElement.addClass('language-abap');

		var newHtmlForElement = thisElement.html();
		newHtmlForElement = replaceAll(newHtmlForElement,	'
',	'\n');

		newHtmlForElement = '' + newHtmlForElement + '';

		// Prevents Highlighting of non ABAP comments
		newHtmlForElement = replaceAll(newHtmlForElement, '*\n>>>', '*\n>>>');
		newHtmlForElement = replaceAll(newHtmlForElement, '<<<\n\n*&', '<<<\n\n*&');

		thisElement.html(newHtmlForElement);
		Prism.highlightAll();

		commonCIPostProcessing(thisElement, function(noteNumber) {
			return '/#/notes/' + noteNumber;
		});
	}
});

$( document ).on('DOMNodeInserted', 'pre', function(eventObject) {
	var thisElement = $(this);

	if(!thisElement.hasClass('code-highlighted')) {
		changingPres = true;

		thisElement.addClass('code-highlighted');

		var newHtmlForElement = thisElement.html();
		newHtmlForElement = replaceAll(newHtmlForElement,	'
',	'\n');

		newHtmlForElement = '' + newHtmlForElement + '';

		// Prevents Highlighting of non ABAP comments
		newHtmlForElement = replaceAll(newHtmlForElement, '*\n>>>', '*\n>>>');
		newHtmlForElement = replaceAll(newHtmlForElement, '<<<\n\n*&', '<<<\n\n*&');

		thisElement.html(newHtmlForElement);
		Prism.highlightAll();

		commonCIPostProcessing(thisElement, function(noteNumber) {
			return '/#/notes/' + noteNumber;
		});
	}
});

Fix after latest update from launchpad


import React from 'react';
import DayPicker from '../../../src';

import styles from '../styles/cssmodules.css';

export default function CSSModules() {
  return (
    <DayPicker
      classNames={styles}
      enableOutsideDays
      initialMonth={new Date(2017, 1)}
      selectedDays={new Date(2017, 1, 23)}
      disabledDays={[new Date(2017, 1, 20), new Date(2018, 1, 28)]}
      modifiers={{
        [styles.sunday]: day => day.getDay() === 0,
        [styles.green]: new Date(2017, 1, 10),
      }}
    />
  );
}

import React from 'react';
import DayPicker from '../../../src';

import styles from '../styles/cssmodules.css';

function handleDayClick(day, modifiers) {
  if (modifiers[styles.green]) {
    console.log('This is a green day');
  }
  if (modifiers[styles.sunday]) {
    console.log('This is Sunday');
  }
}

export default function CSSModules() {
  return (
    <DayPicker
      classNames={styles}
      enableOutsideDays
      initialMonth={new Date(2017, 1)}
      selectedDays={new Date(2017, 1, 23)}
      disabledDays={[new Date(2017, 1, 20), new Date(2018, 1, 28)]}
      modifiers={{
        [styles.sunday]: day => day.getDay() === 0,
        [styles.green]: new Date(2017, 1, 10),
      }}
      onDayClick={handleDayClick}
    />
  );
}

Add onDayClick to CSS modules example


'use strict';

const resolve = require('resolve');

function loadPlugin(plugin, paths) {
  if (typeof plugin === 'string') {
    // Apply the plugin with default options if passing only a string
    return loadPlugin({ name: plugin }, paths);
  }

  if (typeof plugin === 'function') {
    return [plugin, {}];
  }

  if (typeof plugin.func === 'function') {
    // Used for writing plugin tests
    return [plugin.func, plugin.options];
  }

  if (typeof plugin.object === 'object') {
    // Used for writing plugin tests
    return [plugin.object, plugin.options];
  }

  const completePluginNames = [`razzle-plugin-${plugin.name}`, `${plugin.name}/razzle-plugin`];

  // Try to find the plugin in node_modules
  let razzlePlugin = null;
  for (const completePluginName of completePluginNames) {
    razzlePlugin = require(completePluginName);
    if (razzlePlugin) {
      break;
    }
  }

  if (!razzlePlugin) {
    throw new Error(`Unable to find '${completePluginName[0]}' or '${completePluginName[1]}'`);
  }

  return [razzlePlugin, plugin.options];
}

function loadPlugins(plugins, paths) {
  return plugins.map(function(plugin) {
    return loadPlugin(plugin, paths);
  });
}

module.exports = loadPlugins;

'use strict';

const resolve = require('resolve');

function loadPlugin(plugin, paths) {
  if (typeof plugin === 'string') {
    // Apply the plugin with default options if passing only a string
    return loadPlugin({ name: plugin }, paths);
  }

  if (typeof plugin === 'function') {
    return [plugin, {}];
  }

  // Support for not released plugins
  if (typeof plugin === 'object') {
    return [plugin, {}];
  }

  if (typeof plugin.func === 'function') {
    // Used for writing plugin tests
    return [plugin.func, plugin.options];
  }

  if (typeof plugin.object === 'object') {
    // Used for writing plugin tests
    return [plugin.object, plugin.options];
  }

  const completePluginNames = [`razzle-plugin-${plugin.name}`, `${plugin.name}/razzle-plugin`];

  // Try to find the plugin in node_modules
  let razzlePlugin = null;
  for (const completePluginName of completePluginNames) {
    razzlePlugin = require(completePluginName);
    if (razzlePlugin) {
      break;
    }
  }

  if (!razzlePlugin) {
    throw new Error(`Unable to find '${completePluginName[0]}' or '${completePluginName[1]}'`);
  }

  return [razzlePlugin, plugin.options];
}

function loadPlugins(plugins, paths) {
  return plugins.map(function(plugin) {
    return loadPlugin(plugin, paths);
  });
}

module.exports = loadPlugins;

Support for not released plugins in razzle.config.js


/**
 * Internal counter for added top hits aggregations.
 * @type {Number}
 */
let count = 0;

/**
 * Construct a Top hits aggregation.
 *
 * @param  {Object} opts  Options to include in the aggregation (maybe empty).
 * @param  {String} name  Aggregation name. Defaults to agg_top_hits_{count}.
 * @return {Object}       Top hits Aggregation.
 */
export default function topHitsAggregation(opts, name) {
  name = name || `agg_top_hits_${count++}`
  return {
    [name]: {
      top_hits: opts || {}
    }
  }
}

/**
 * Internal counter for added top hits aggregations.
 * @type {Number}
 */
let count = 0;

/**
 * Construct a Top hits aggregation.
 *
 * @param  {Object} opts  Options to include in the aggregation. Defaults to {}.
 * @param  {String} name  Aggregation name. Defaults to 'agg_top_hits_{count}'.
 * @return {Object}       Top hits Aggregation.
 */
export default function topHitsAggregation(opts = {}, name) {
  name = name || `agg_top_hits_${count++}`
  return {
    [name]: {
      top_hits: opts
    }
  }
}

Make use of ES6 default param values on topHitsAggregation


/**
 * Export javascript style and css style vendor prefixes.
 * Based on "transform" support test.
 */

import isBrowser from 'is-browser'

let js = ''
let css = ''

// We should not do anything if required serverside.
if (isBrowser) {
  const jsCssMap = {
    Webkit: '-webkit-',
    Moz: '-moz-',
    // IE did it wrong again ...
    ms: '-ms-',
    O: '-o-'
  }

  // Order matters. We need to check Webkit the last one because
  // other vendors use to add Webkit prefixes to some properties
  const prefixes = ['Moz', 'ms', 'O', 'Webkit']

  const style = document.createElement('p').style
  const testProp = 'Transform'

  for (let i = 0; i < prefixes.length; i++) {
    const prefix = prefixes[i];
    if ((prefix + testProp) in style) {
      js = prefix
      css = jsCssMap[prefix]
      break
    }
  }
}

/**
 * Vendor prefix string for the current browser.
 *
 * @type {{js: String, css: String}}
 * @api public
 */
export default {js, css}

/**
 * Export javascript style and css style vendor prefixes.
 * Based on "transform" support test.
 */

import isBrowser from 'is-browser'

let js = ''
let css = ''

// We should not do anything if required serverside.
if (isBrowser) {
  // Order matters. We need to check Webkit the last one because
  // other vendors use to add Webkit prefixes to some properties
  const jsCssMap = {
    Moz: '-moz-',
    // IE did it wrong again ...
    ms: '-ms-',
    O: '-o-',
    Webkit: '-webkit-'
  }
  const style = document.createElement('p').style
  const testProp = 'Transform'

  for (const key in jsCssMap) {
    if ((key + testProp) in style) {
      js = key
      css = jsCssMap[key]
      break
    }
  }
}

/**
 * Vendor prefix string for the current browser.
 *
 * @type {{js: String, css: String}}
 * @api public
 */
export default {js, css}

Use the original object instead of array


/* eslint no-console: off */
import build from "./scripts/build"
import start from "./scripts/start"
import bootstrap from "./scripts/bootstrap"

const ARGSPOS_SCRIPT = 2
const ARGSPOS_ARGUMENTS = 3

var script = process.argv[ARGSPOS_SCRIPT]
var args = process.argv.slice(ARGSPOS_ARGUMENTS)

switch (script)
{
  case "build":
    build(args)
    break

  case "start":
    start(args)
    break

  case "bootstrap":
    bootstrap(args)
    break

  case null:
  case undefined:
    console.log("No script name given!")
    break

  default:
    console.log(`Unknown script "${script}"!`)
    break
}

/* eslint-disable no-console */
import chalk from "chalk"

import build from "./scripts/build"
import start from "./scripts/start"
import bootstrap from "./scripts/bootstrap"

import packageConfig from "../package.json"

const ARGSPOS_SCRIPT = 2
const ARGSPOS_ARGUMENTS = 3

var script = process.argv[ARGSPOS_SCRIPT]
var args = process.argv.slice(ARGSPOS_ARGUMENTS)

function header()
{
  console.log(
    chalk.cyan(`\n${packageConfig.name} ${packageConfig.version}`),
    chalk.gray(`\n${packageConfig.description}`),
    "\n"
  )
}
function help()
{
  console.log(
    "\nSyntax: edge <command>",
    "\n\nCommands:",
    "\n  start      Start development server",
    "\n  build      Create production build",
    "\n  bootstrap  Bootstraps a new edge stack project",
    "\n\nOptions for bootstrap:",
    "\n    [--title <title>]               Title of new application",
    "\n    [--description <description>]   Description of new application",
    "\n    [--language <xx-YY>]            Language of application in format xx-YY",
    "\n    [--overwrite <y/n>]             Overwrite existing source code"
  )
}

header()

switch (script)
{
  case "build":
    build(args)
    break

  case "start":
    start(args)
    break

  case "bootstrap":
    bootstrap(args)
    break

  case null:
  case undefined:
    console.log(chalk.red("No script name given!"))
    help()
    break

  default:
    console.log(chalk.red(`Unknown script "${script}"!`))
    help()
    break
}

Add header and help text


// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @implements {Common.Runnable}
 */
export class WorkerMainImpl extends Common.Object {
  /**
   * @override
   */
  run() {
    SDK.initMainConnection(() => {
      self.SDK.targetManager.createTarget('main', ls`Main`, SDK.Target.Type.ServiceWorker, null);
    }, Components.TargetDetachedDialog.webSocketConnectionLost);
    new MobileThrottling.NetworkPanelIndicator();
  }
}

SDK.ChildTargetManager.install(async ({target, waitingForDebugger}) => {
  // Only pause the new worker if debugging SW - we are going through the pause on start checkbox.
  if (target.parentTarget() || target.type() !== SDK.Target.Type.ServiceWorker || !waitingForDebugger) {
    return;
  }
  const debuggerModel = target.model(SDK.DebuggerModel);
  if (!debuggerModel) {
    return;
  }
  if (!debuggerModel.isReadyToPause()) {
    await debuggerModel.once(SDK.DebuggerModel.Events.DebuggerIsReadyToPause);
  }
  debuggerModel.pause();
});

// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import * as Common from '../common/common.js';
import * as Components from '../components/components.js';
import * as MobileThrottling from '../mobile_throttling/mobile_throttling.js';
import * as SDK from '../sdk/sdk.js';

/**
 * @implements {Common.Runnable.Runnable}
 */
export class WorkerMainImpl extends Common.ObjectWrapper.ObjectWrapper {
  /**
   * @override
   */
  run() {
    SDK.Connections.initMainConnection(() => {
      self.SDK.targetManager.createTarget('main', ls`Main`, SDK.SDKModel.Type.ServiceWorker, null);
    }, Components.TargetDetachedDialog.TargetDetachedDialog.webSocketConnectionLost);
    new MobileThrottling.NetworkPanelIndicator.NetworkPanelIndicator();
  }
}

SDK.ChildTargetManager.ChildTargetManager.install(async ({target, waitingForDebugger}) => {
  // Only pause the new worker if debugging SW - we are going through the pause on start checkbox.
  if (target.parentTarget() || target.type() !== SDK.SDKModel.Type.ServiceWorker || !waitingForDebugger) {
    return;
  }
  const debuggerModel = target.model(SDK.DebuggerModel.DebuggerModel);
  if (!debuggerModel) {
    return;
  }
  if (!debuggerModel.isReadyToPause()) {
    await debuggerModel.once(SDK.DebuggerModel.Events.DebuggerIsReadyToPause);
  }
  debuggerModel.pause();
});

Migrate worker_main/ to import cross-module


$j(document).ready(function () {
    'use strict';
    if (window.location.pathname.indexOf('lunchtransactions.html') === -1) {
      var newLaunchBox = $j('#ptgNewLaunchBox');

      // Removes Older Launch link
      newLaunchBox.find('p').eq(2).remove();
      // Rename Gradebook Launch header
      $j('#ptgNewLaunchBox').find('h2').text('Old Gradebook');
    }
});

import $ from 'jquery';

export default function() {
  $(() => {
      if (window.location.pathname.indexOf('lunchtransactions.html') === -1) {
        var newLaunchBox = $('#ptgNewLaunchBox');

        // Removes Older Launch link
        newLaunchBox.find('p').eq(2).remove();
        // Rename Gradebook Launch header
        $('#ptgNewLaunchBox').find('h2').text('Old Gradebook');
      }
  });
}

Use es6 module syntax to import jquery


const uuid = require('uuid');
const express = require('express');
const router = express.Router();
const Promise = require('bluebird');
const logger = require('../../logger');

const { getPathwayJson } = require('./generate-pathway-json');

const db = require('../../db');

let findPathwayByUri = uri => {
  return db.accessTable('pathways').then( res => {
    let { table, conn } = res;

    return (
      table.filter({ uri: uri })
        .limit( 1 )
        .run( conn )
        .then( cursor => cursor.toArray() )
        .then( results => {
          if( results.length > 0 ){
            return results[0].network;
          } else {
            return null;
          }
        } )
    );
  });
};

let insertPathway = ( pathwayJson, uri ) => {
  return db.accessTable('pathways').then( res => {
    let { table, conn } = res;

    return (
      table.insert({
        id: uuid(),
        uri: uri,
        network: pathwayJson
      })
      .run( conn )
      .then( () => pathwayJson )
    );
  });
};

let getAndStorePathway = ( uri ) => {
  return getPathwayJson( uri ).then( pathwayJson => insertPathway( pathwayJson, uri ) );
};

router.get('/', ( req, res ) => {
  let uri = req.query.uri;

  let find = () => findPathwayByUri( uri );
  let storeIfNoResult = result => result != null ? result : getAndStorePathway( uri );
  let sendResponse = result => res.json(result);

  ( Promise.try(find)
    .then(storeIfNoResult)
    .then(sendResponse)
    .catch( err => {
      logger.error( err );
      res.status( 500 ).end( 'Server error' );
    } )
  );
});

module.exports = router;

const express = require('express');
const router = express.Router();
const Promise = require('bluebird');
const logger = require('../../logger');

const { getPathwayJson } = require('./generate-pathway-json');

router.get('/', ( req, res ) => {
  let uri = req.query.uri;

  let find = () => getPathwayJson( uri );
  let sendResponse = result => res.json(result);

  ( Promise.try(find)
    .then(sendResponse)
    .catch( err => {
      logger.error( err );
      res.status( 500 ).end( 'Server error' );
    } )
  );
});

module.exports = router;

Remove DB code for pathways


/*
 * syndicate-g
 * https://github.com/petarov/syndicate-g
 *
 * The MIT License (MIT)
 * Copyright (c) 2013 Petar Petrov
 */
"use strict";

var _ = require('underscore')._;
var Redis = require('redis');

var cli;

/**
 * Exports
 */
module.exports = function(config) {
  return {
    open: function(options) {
      cli = Redis.createClient(config.db.redis_port, config.db.redis_host);
      config.db.redis_secret && cli.auth(config.db.redis_secret);

      cli.on('error', function (err) {
        console.log(err);
      });
    },

    close: function() {
      cli && cli.quit();
    },

    put: function(key, value, callback) {
      cli.set(key, value, callback);
    },

    get: function(key, callback) {
      cli.get(key, function(err, value) {
        if (value == null) {
          callback({notFound: true}, null);
          return;
        }
        callback(err, value);
      });
    },

    delete: function(key, callback) {
      cli.del(key, callback);
    }
  };
}

/*
 * syndicate-g
 * https://github.com/petarov/syndicate-g
 *
 * The MIT License (MIT)
 * Copyright (c) 2013 Petar Petrov
 */
"use strict";

var _ = require('underscore')._;
var Redis = require('redis');

var cli;

/**
 * Exports
 */
module.exports = function(config) {
  return {
    open: function(options) {
      if (config.db.redis_port) {
          cli = Redis.createClient(config.db.redis_port, config.db.redis_host);
      } else {
          cli = Redis.createClient(config.db.redis_host);
      }

      config.db.redis_secret && cli.auth(config.db.redis_secret);

      cli.on('error', function (err) {
        console.log(err);
      });
    },

    close: function() {
      cli && cli.quit();
    },

    put: function(key, value, callback) {
      cli.set(key, value, callback);
    },

    get: function(key, callback) {
      cli.get(key, function(err, value) {
        if (value == null) {
          callback({notFound: true}, null);
          return;
        }
        callback(err, value);
      });
    },

    delete: function(key, callback) {
      cli.del(key, callback);
    }
  };
}

Add an option to use a Redis credentials url


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

var npm = function(str) {
  var deps = JSON.parse(str).dependencies;
  return Object.keys(deps)
  .reduce(function(accum, dep) {
    accum.push([dep, deps[dep]]);
    return accum;
  }, []);
};

module.exports = npm;

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

var npm = function(str) {
  var json;
  try { json = JSON.parse(str); } catch(err) { return []; }
  var allDeps = Object.assign({}, json.dependencies, json.devDependencies);
  return Object.keys(allDeps)
  .reduce(function(accum, dep) {
    accum.push([dep, allDeps[dep]]);
    return accum;
  }, []);
};

module.exports = npm;

Support for devDeps in NPM and safer parsing


(function($){
  "use strict";

  var url = "http://devitconf.org/";

  var devit = {

    init: function () {
      devit.getSocialCounts();
      devit.setCurrentYear();
    },

    getSocialCounts: function () {
      $.getJSON(
        "http://urls.api.twitter.com/1/urls/count.json?url=" + url + "&callback=?",
        function (json) {
          $('.js-tw-count').text(devit._getK(json.count));
        }
      );

      $.getJSON(
        "http://graph.facebook.com/" + url,
        function (json) {
          $('.js-fb-count').text(devit._getK(json.shares));
        }
      );
    },

    _getK: function(n) {
      var c = parseInt(n);

      if (c > 9999 && c <= 999999) {
        return parseFloat((c / 1000).toFixed(1)) + 'k';
      } else if (c > 999999) {
        return parseFloat((c / 1000000).toFixed(1)) + 'm';
      } else {
        return c;
      }
    },

    setCurrentYear: function () {
      var currentYear = new Date().getFullYear();
      $('.js-current-year').text(currentYear);
    }
  };

  $(document).ready(function () {
    devit.init();
  });

})(jQuery);

(function($){
  "use strict";

  var url = "http://devitconf.org/";

  var devit = {

    init: function () {
      devit.getSocialCounts();
      devit.setCurrentYear();
    },

    getSocialCounts: function () {
      $.getJSON(
        "http://urls.api.twitter.com/1/urls/count.json?url=" + url + "&callback=?",
        function (json) {
          $('.js-tw-count').text(devit.siAbbrevCount(json.count));
        }
      );

      $.getJSON(
        "http://graph.facebook.com/" + url,
        function (json) {
          $('.js-fb-count').text(devit.siAbbrevCount(json.shares));
        }
      );
    },

    siAbbrevCount: function(n) {
      var c = parseInt(n);

      if (c > 9999 && c <= 999999) {
        return parseFloat((c / 1000).toFixed(1)) + 'k';
      } else if (c > 999999) {
        return parseFloat((c / 1000000).toFixed(1)) + 'm';
      } else {
        return c;
      }
    },

    setCurrentYear: function () {
      var currentYear = new Date().getFullYear();
      $('.js-current-year').text(currentYear);
    }
  };

  $(document).ready(function () {
    devit.init();
  });

})(jQuery);

Rename _getK() to be more descriptive


import { takeEvery, all, put, select } from 'redux-saga/effects';
import { fetchDataAction } from 'controllers/fetch';
import { activeProjectSelector } from 'controllers/user';
import { URLS } from 'common/urls';
import { NAMESPACE, FETCH_EVENTS } from './constants';
import { querySelector } from './selectors';

function* fetchEvents() {
  const projectId = yield select(activeProjectSelector);
  const query = yield select(querySelector);
  yield put(
    fetchDataAction(NAMESPACE)(URLS.events(projectId), {
      params: { ...query },
    }),
  );
}

function* watchFetchEvents() {
  yield takeEvery(FETCH_EVENTS, fetchEvents);
}

export function* eventsSagas() {
  yield all([watchFetchEvents()]);
}

import { takeEvery, all, put, select } from 'redux-saga/effects';
import { fetchDataAction } from 'controllers/fetch';
import { projectIdSelector } from 'controllers/pages';
import { URLS } from 'common/urls';
import { NAMESPACE, FETCH_EVENTS } from './constants';
import { querySelector } from './selectors';

function* fetchEvents() {
  const projectId = yield select(projectIdSelector);
  const query = yield select(querySelector);
  yield put(
    fetchDataAction(NAMESPACE)(URLS.events(projectId), {
      params: { ...query },
    }),
  );
}

function* watchFetchEvents() {
  yield takeEvery(FETCH_EVENTS, fetchEvents);
}

export function* eventsSagas() {
  yield all([watchFetchEvents()]);
}

Fix project url on events page


exports.get = function get (obj, key) {
  for (var i in obj) if (i.toLowerCase() === key.toLowerCase()) return obj[i];
  return undefined;
};
exports.set = function set (obj, key, val) {
  for (var i in obj) if (i.toLowerCase() === key.toLowerCase()) return obj[i] = val;
  return obj[key] = val;
};

exports.bind = function bind (o, fn) {
  return function () {
    return fn.apply(o, arguments);
  };
};

exports.method = function method (o, fn) {
  return function () {
    return o[fn].apply(o, arguments);
  };
};

exports.log = function log (msg, pref) {
  pref = (pref && ": " + pref) || "";
  if (msg) msg = "npm"+pref+": "+msg;
  node.stdio.writeError(msg+"\n");
};

exports.array = function array (arr) {
  return Array.prototype.slice.call(arr,0);
};

module.exports = {
  set:set,
  bind:bind,
  method:method,
  log:log,
  array:array,
  succeed:succeed,
  fail:fail
};

function get (obj, key) {
  for (var i in obj) if (i.toLowerCase() === key.toLowerCase()) return obj[i];
  return undefined;
};

function set (obj, key, val) {
  for (var i in obj) if (i.toLowerCase() === key.toLowerCase()) return obj[i] = val;
  return obj[key] = val;
};

function has (obj, key) {
  for (var i in obj) if (obj.hasOwnProperty(i) && i.toLowerCase === key.toLowerCase()) return true;
  return false;
};

function bind (o, fn) {
  var args = array(arguments, 2);
  return function () {
    return fn.apply(o, args.concat(array(arguments)));
  };
};

function method (o, fn) {
  var args = array(arguments, 2);
  return function () {
    return o[fn].apply(o, args.concat(array(arguments)));
  };
};

function log (msg, pref) {
  pref = (pref && ": " + pref) || "";
  if (msg) msg = "npm"+pref+": "+msg;
  node.stdio.writeError(msg+"\n");
};

function array (arr, n) {
  return Array.prototype.slice.call(arr,n || 0);
};

function succeed (p) {
  return method(p, "emitSuccess", array(arguments,1));
};
function fail (p) {
  return method(p, "emitError", array(arguments,1));
}

Reorganize this file a little bit.


'use strict';

/**
 * @ngdoc function
 * @name websocketTesterApp.controller:MainCtrl
 * @description
 * # MainCtrl
 * Controller of the websocketTesterApp
 */
angular.module('websocketTesterApp')
  .controller('MainCtrl', function ($window, $rootScope, $log, $websocket) {

    var self,
        socket;

    self = this;

    function pushDialogue(message) {
      $rootScope.$broadcast('ADD_LOG_LINE', message);
    }

    self.connect = function(url) {
      try {
        socket = $websocket(url);
      } catch (e) {
        pushDialogue('*** Error: ' + e.message);
        return;
      }

      socket.onOpen(function() {
        pushDialogue('*** Connected to: ' + url);
      });

      socket.onClose(function() {
        pushDialogue('*** Disconnected from: ' + url);
      });

      socket.onError(function() {
        pushDialogue('*** Error: Check browser console for more information');
      });

      socket.onMessage(function(message) {
        pushDialogue('->' + message.data);
      });

    };

    self.disconnect = function() {
      socket.close();
    };

    self.send = function(message) {
      socket.send(message).then(function() {
        pushDialogue('<-' + message);
      });
    };

  });

'use strict';

/**
 * @ngdoc function
 * @name websocketTesterApp.controller:MainCtrl
 * @description
 * # MainCtrl
 * Controller of the websocketTesterApp
 */
angular.module('websocketTesterApp')
  .controller('MainCtrl', function ($window, $scope, $log, $websocket) {

    var self,
        socket;

    self = this;

    function pushDialogue(message) {
      $scope.$broadcast('ADD_LOG_LINE', message);
    }

    self.connect = function(url) {
      try {
        socket = $websocket(url);
      } catch (e) {
        pushDialogue('*** Error: ' + e.message);
        return;
      }

      socket.onOpen(function() {
        pushDialogue('*** Connected to: ' + url);
      });

      socket.onClose(function() {
        pushDialogue('*** Disconnected from: ' + url);
      });

      socket.onError(function() {
        pushDialogue('*** Error: Check browser console for more information');
      });

      socket.onMessage(function(message) {
        pushDialogue('->' + message.data);
      });

    };

    self.disconnect = function() {
      socket.close();
    };

    self.send = function(message) {
      socket.send(message).then(function() {
        pushDialogue('<-' + message);
      });
    };

  });

Reduce scope of event broadcast


// for use with `d3-playbooks-riot-components`

export default ({
  data,
  yCol,
  getColor
}, {getLabel}) => {
  if (!getLabel) getLabel = q => Math.round(q)
  return getColor.quantiles().map(q => {
    return {
      label: getLabel(q),
      color: getColor(q)
    }
  })
}

// for use with `d3-playbooks-riot-components`

export default ({
  yDomain,
  getColor
}, {getLabel}) => {
  if (!getLabel) getLabel = q => Math.round(q)
  const quantiles = getColor.quantiles()
  const quantileWidth = quantiles[0]
  quantiles.push(yDomain[1])
  return quantiles.map(q => {
    return {
      label: getLabel(q),
      color: getColor(q-quantileWidth/2)
    }
  })
}

Add maximum extent value to quantiles for legend


import * as constants from "./constants";

let initNum = 1;
function Attractor(game, center) {
    this.type = "attractor";
    this.id = initNum;
    this.isAlive = true;

    this.game = game;
    this.center = center;
    this.mass = constants.EarthMass * 2 * initNum;

    this.radius = this.mass / constants.EarthMass * constants.EarthRadius;

    initNum++;
}

Attractor.prototype.calculateMass = function() {
    this.mass = this.radius / constants.EarthRadius * constants.EarthMass;
};

Attractor.prototype.update = function () {
    this.color = `hsl(${360 / this.game.attractors.length * this.id}, 100%, 50%)`;
};

export default Attractor;

import * as constants from "./constants";

let initNum = 1;
function Attractor(game, center) {
    this.type = "attractor";
    this.id = initNum;
    this.isAlive = true;

    this.game = game;
    this.center = center;
    this.mass = constants.EarthMass * 4;

    this.radius = this.mass / constants.EarthMass * constants.EarthRadius;

    initNum++;
}

Attractor.prototype.calculateMass = function() {
    this.mass = this.radius / constants.EarthRadius * constants.EarthMass;
};

Attractor.prototype.update = function () {
    this.color = `hsl(${360 / this.game.attractors.length * this.id}, 100%, 50%)`;
};

export default Attractor;

Change attractors to all be the same initial size. This avoids the issue when spawning a large amount of attractors in manually.