var express = require('express');
var health = require('./health.js');
var message = require('./message.js');

var log4js = require('log4js');
var logger = log4js.getLogger('Routes');

var router = express.Router();

router.get('/',health.healthCheck);
router.post('/message',message.sendMessage);

//Exports router
module.exports = router;

var express = require('express');
var health = require('./views/health.js');
var message = require('./views/message.js');

var log4js = require('log4js');
var logger = log4js.getLogger('Routes');

var router = express.Router();

router.get('/',health.healthCheck);
router.post('/message',message.sendMessage);

//Exports router
module.exports = router;

Fix the path of required module


const mongoose = require('mongoose')
const Promise = require('bluebird')

mongoose.Promise = Promise

const uri = process.env.MONGOLAB_URI || 'mongodb://localhost/literasee'

function open(callback) {
  const _open = (resolve, reject) => {
    mongoose
      .connect(uri)
      .connection.on('error', function(err) {
        console.error.bind(console, 'connection error:')
        reject(err)
      })
      .once('open', function() {
        console.log('Connected to database at %s', uri)
        resolve(mongoose.connection)
      })
  }

  return new Promise(_open).nodeify(callback)
}

function close(callback) {
  const _close = (resolve, reject) => {
    mongoose.disconnect(function() {
      console.log('Disconnected from database at %s', uri)
      resolve(mongoose.connection)
    })
  }

  return new Promise(_close).nodeify(callback)
}

module.exports = { open, close }

const mongoose = require('mongoose')
const Promise = require('bluebird')

mongoose.Promise = Promise

const uri = process.env.MONGOLAB_URI || 'mongodb://localhost/literasee'

function open(callback) {
  const _open = (resolve, reject) => {
    mongoose.connect(uri, { useMongoClient: true }).then(
      () => {
        console.log('Connected to database at %s', uri)
        resolve(mongoose.connection)
      },
      err => {
        console.error.bind(console, 'connection error:')
        reject(err)
      },
    )
  }

  return new Promise(_open).nodeify(callback)
}

function close(callback) {
  const _close = (resolve, reject) => {
    mongoose.disconnect(function() {
      console.log('Disconnected from database at %s', uri)
      resolve(mongoose.connection)
    })
  }

  return new Promise(_close).nodeify(callback)
}

module.exports = { open, close }

Update mongoose connection code per deprecations


import React, { Component } from 'react';
import DocumentTitle from 'react-document-title';

import PurposeCategoryList from 'containers/PurposeCategoryList';

class HomePage extends Component {
  render() {
    return (
      <DocumentTitle title="Etusivu - Varaamo">

Varaa vaivatta kaupungin tiloja ja laitteita

            Varaustilanteen näet kirjautumatta. Varaaminen edellyttää kirjautumista. Kyseessä on
            kokeiluasteella oleva palvelu, jonka kautta varataan Kaupunginkirjaston,
            Nuorisoasiainkeskuksen ja Varhaiskasvatusviraston tiloja ja työpisteitä.

Mitä haluat tehdä?

          <PurposeCategoryList />

      </DocumentTitle>
    );
  }
}

HomePage.propTypes = {};

export default HomePage;

import React, { Component } from 'react';
import DocumentTitle from 'react-document-title';

import PurposeCategoryList from 'containers/PurposeCategoryList';

class HomePage extends Component {
  render() {
    return (
      <DocumentTitle title="Etusivu - Varaamo">

Varaa vaivatta kaupungin tiloja ja laitteita

            Varaustilanteen näet kirjautumatta. Varaaminen edellyttää kirjautumista. Kyseessä on
            kokeiluasteella oleva palvelu, jonka kautta varataan kaupunginkirjaston,
            nuorisoasiainkeskuksen ja varhaiskasvatusviraston tiloja ja työpisteitä.

Mitä haluat tehdä?

          <PurposeCategoryList />

      </DocumentTitle>
    );
  }
}

HomePage.propTypes = {};

export default HomePage;

Fix capitalization on home page text


import Ember from 'ember';

export default Ember.Controller.extend({
  queryParams: ['viewType', 'nodeId'],
  query: Ember.inject.service(),
  viewType: 'live',

  modelArrived: Ember.observer('model', function() {
    const nodeList = this.get('model.nodes');
    const nodeTuples = nodeList.map(node => {
      return [node.properties.id, node.properties];
    });
    const nodeMap = new Map(nodeTuples);
    this.set('nodeMap', nodeMap);
    if (!this.get('nodeId')) {
      this.set('nodeId', nodeList[0].properties.id);
    }
  }),

  selectedNodeMeta: Ember.computed('nodeId', function() {
    const nodeMap = this.get('nodeMap');
    return nodeMap.get(this.get('nodeId'));
  }),

  actions: {
    onSelect(nodeId) {
      this.set('nodeId', nodeId);
    },
    download(params) {
      this.get('query').sensorDownload(params).then(resp => {
        this.transitionToRoute('datadump.download', resp.ticket, {queryParams: {data_type: 'csv'}});
      });
    }
  }
});

import Ember from 'ember';

export default Ember.Controller.extend({
  queryParams: ['viewType', 'nodeId'],
  query: Ember.inject.service(),
  viewType: 'live',
  notify: Ember.inject.service(),

  modelArrived: Ember.observer('model', function() {
    const nodeList = this.get('model.nodes');
    const nodeTuples = nodeList.map(node => {
      return [node.properties.id, node.properties];
    });
    const nodeMap = new Map(nodeTuples);
    this.set('nodeMap', nodeMap);
    if (!this.get('nodeId')) {
      this.set('nodeId', nodeList[0].properties.id);
    }
  }),

  selectedNodeMeta: Ember.computed('nodeId', function() {
    const nodeMap = this.get('nodeMap');
    return nodeMap.get(this.get('nodeId'));
  }),

  actions: {
    onSelect(nodeId) {
      this.set('nodeId', nodeId);
    },
    download(params) {
      this.get('query').sensorDownload(params).then(resp => {
        this.transitionToRoute('datadump.download', resp.ticket, {queryParams: {data_type: 'csv'}});
      }).catch(() => {
          this.get('notify').error('Could not process request. ' +
            'Try double-checking your request, and email plenario@uchicago.edu if the problem persists.');
        }
      );
    }
  }
});

Add error catch to download component


// @flow

import * as React from 'react';
import { View, Text, StyleSheet } from 'react-native';

import { threadTypes, type ThreadType } from 'lib/types/thread-types';

import ThreadIcon from './thread-icon.react';

type Props = {|
  +threadType: ThreadType,
  +color: string,
|};
function ThreadVisibility(props: Props) {
  const { threadType, color } = props;
  const visLabelStyle = [styles.visibilityLabel, { color }];

  let label;
  if (threadType === threadTypes.CHAT_SECRET) {
    label = 'Secret';
  } else if (threadType === threadTypes.PRIVATE) {
    label = 'Private';
  } else {
    label = 'Open';
  }

  return (
    <View style={styles.container}>
      <ThreadIcon threadType={threadType} color={color} />
      <Text style={visLabelStyle}>{label}</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    alignItems: 'center',
    flexDirection: 'row',
  },
  visibilityLabel: {
    fontSize: 16,
    fontWeight: 'bold',
    paddingLeft: 4,
  },
});

export default ThreadVisibility;

// @flow

import * as React from 'react';
import { View, Text, StyleSheet } from 'react-native';

import { threadLabel } from 'lib/shared/thread-utils';
import type { ThreadType } from 'lib/types/thread-types';

import ThreadIcon from './thread-icon.react';

type Props = {|
  +threadType: ThreadType,
  +color: string,
|};
function ThreadVisibility(props: Props) {
  const { threadType, color } = props;
  const visLabelStyle = [styles.visibilityLabel, { color }];
  const label = threadLabel(threadType);

  return (
    <View style={styles.container}>
      <ThreadIcon threadType={threadType} color={color} />
      <Text style={visLabelStyle}>{label}</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    alignItems: 'center',
    flexDirection: 'row',
  },
  visibilityLabel: {
    fontSize: 16,
    fontWeight: 'bold',
    paddingLeft: 4,
  },
});

export default ThreadVisibility;

Use threadLabel function in ThreadVisibility


var express  = require('express');
var request  = require('request');
var auth = require('./lib/auth.js');

var app = express();
var localfile = express.static(__dirname + '/app');
// configure Express
app.configure(function() {
  app.set('views', __dirname + '/views');
  app.set('view engine', 'ejs');
  app.use(express.logger());
  app.use(express.cookieParser());
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(express.session({ secret: 'what? ok!' }));
// Initialize Passport!  Also use passport.session() middleware, to support
// persistent login sessions (recommended).
  app.use(auth.initialize());
  app.use(auth.session());
  app.use(app.router);
  app.use(localfile);
});

// app.all('*', requireAuthentication)
// app.all('*', loadUser);

var usersExist = function() {
	return false;
};

app.get("/", function(req, res) {
	if (!usersExist()) {
		res.redirect('/client/#/config');
	}
	else {
		localfile(req, res);
	}
});

app.get("/data/what", auth.ensure, function(req, res) {
	res.send(req.user);
});

app.post('/login', auth.authenticate('/login'), function(req, res) {
   	res.redirect('/');
});

app.listen(80);

var express  = require('express');
var request  = require('request');
var auth = require('./lib/auth.js');

var app = express();
var localfile = express.static(__dirname + '/app');
// configure Express
app.configure(function() {
  app.set('views', __dirname + '/views');
  app.set('view engine', 'ejs');
  app.use(express.logger());
  app.use(express.cookieParser());
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(express.session({ secret: 'what? ok!' }));
// Initialize Passport!  Also use passport.session() middleware, to support
// persistent login sessions (recommended).
  app.use(auth.initialize());
  app.use(auth.session());
  app.use(app.router);
  app.use(localfile);
});

// app.all('*', requireAuthentication)
// app.all('*', loadUser);

var usersExist = function() {
	return false;
};

app.get("/", function(req, res) {
	if (!usersExist()) {
		res.redirect('/client/#/config');
	}
	else {
		localfile(req, res);
	}
});

app.get("/data/what", auth.ensure, function(req, res) {
	res.send(req.user);
});

app.post('/login', auth.authenticate('/login'), function(req, res) {
   	res.redirect('/');
});

app.listen(8080);

Change default port to 8080


/**
 * Created by netanel on 01/01/15.
 */

var minify = Npm.require('html-minifier').minify;
Plugin.registerSourceHandler('tpl', {
  isTemplate: true,
  archMatching: "web"
}, function(compileStep) {
  var contents = compileStep.read().toString('utf8');

  var results = 'angular.module(\'angular-meteor\').run([\'$templateCache\', function($templateCache) {' +
    // Since compileStep.inputPath uses backslashes on Windows, we need replace them
    // with forward slashes to be able to consistently include templates across platforms.
    // Ticket here: https://github.com/Urigo/angular-meteor/issues/169
    // A standardized solution to this problem might be on its way, see this ticket:
    // https://github.com/meteor/windows-preview/issues/47
    '$templateCache.put(\'' + compileStep.inputPath.replace(/\\/g, "/") + '\', \'' +
      minify(contents.replace(/'/g, "\\'"), {
        collapseWhitespace : true,
        removeComments : true,
        minifyJS : true,
        minifyCSS: true,
        processScripts : ['text/ng-template']
      }) + '\');' +
    '}]);';

  compileStep.addJavaScript({
    path : compileStep.inputPath,
    data : results,
    sourcePath : compileStep.inputPath
  });
});

/**
 * Created by netanel on 01/01/15.
 */

var minify = Npm.require('html-minifier').minify;
Plugin.registerSourceHandler('ng.html', {
  isTemplate: true,
  archMatching: "web"
}, function(compileStep) {
  var contents = compileStep.read().toString('utf8');

  var results = 'angular.module(\'angular-meteor\').run([\'$templateCache\', function($templateCache) {' +
    // Since compileStep.inputPath uses backslashes on Windows, we need replace them
    // with forward slashes to be able to consistently include templates across platforms.
    // Ticket here: https://github.com/Urigo/angular-meteor/issues/169
    // A standardized solution to this problem might be on its way, see this ticket:
    // https://github.com/meteor/windows-preview/issues/47
    '$templateCache.put(\'' + compileStep.inputPath.replace(/\\/g, "/") + '\', \'' +
      minify(contents.replace(/'/g, "\\'"), {
        collapseWhitespace : true,
        removeComments : true,
        minifyJS : true,
        minifyCSS: true,
        processScripts : ['text/ng-template']
      }) + '\');' +
    '}]);';

  compileStep.addJavaScript({
    path : compileStep.inputPath,
    data : results,
    sourcePath : compileStep.inputPath
  });
});

Change template extension from .tpl to .ng.html


const webpack = require('webpack');

module.exports = {
  plugins: [
    new webpack.NoEmitOnErrorsPlugin(),
  ],
};

const webpack = require('webpack');

module.exports = {
  plugins: [
    // This plugin does not swallow errors. Instead, it just prevents
    // Webpack from printing out compile time stats to the console.
    new webpack.NoEmitOnErrorsPlugin(),
  ],
};

Add notes to no emit error plugin


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

export class RadioGroup extends React.Component {
  static propTypes = {
    id: PropTypes.string,
    name: PropTypes.string,
    onChange: PropTypes.func,
    value: PropTypes.any
  };

  componentDidMount() {
    require('../../css/forms');
  }

  render() {
    const {name, children, onChange, className, value, ...others} = this.props;
    const radioProps = onChange ? {name, onChange} : {name};

    return (
      <div {...{...others, className: classnames('pui-radio-group', className)}}>
        {React.Children.map(children, child =>
          React.cloneElement(child, {...radioProps, checked: child.props.value === value}))}
      </div>
    );
  }
}

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

export class RadioGroup extends React.Component {
  static propTypes = {
    id: PropTypes.string,
    name: PropTypes.string,
    onChange: PropTypes.func,
    value: PropTypes.any
  };

  componentDidMount() {
    require('../../css/forms');
  }

  render() {
    const {name, children, onChange, className, value, ...others} = this.props;
    const radioProps = onChange ? {name, onChange} : {name, readOnly: true};

    return (
      <div {...{...others, className: classnames('pui-radio-group', className)}}>
        {React.Children.map(children, child =>
          React.cloneElement(child, {...radioProps, checked: child.props.value === value}))}
      </div>
    );
  }
}

Set readOnly: true on Radios in RadioGroups without onChanges to fix React warning


import React from 'react'

import { enterHotUpdate } from '../global/generation'
import AppContainer from '../AppContainer.dev'
import { resolveType } from './resolver'

const lazyConstructor = '_ctor'

export const updateLazy = (target, type) => {
  const ctor = type[lazyConstructor]
  if (target[lazyConstructor] !== type[lazyConstructor]) {
    // just execute `import` and RHL.register will do the job
    ctor()
  }
  if (!target[lazyConstructor].isPatchedByReactHotLoader) {
    target[lazyConstructor] = () =>
      ctor().then(m => {
        const C = resolveType(m.default)
        // chunks has been updated - new hot loader process is taking a place
        enterHotUpdate()
        return {
          default: props => (
            <AppContainer>
              <C {...props} />
            </AppContainer>
          ),
        }
      })
    target[lazyConstructor].isPatchedByReactHotLoader = true
  }
}

export const updateMemo = (target, { type }) => {
  target.type = resolveType(type)
}

export const updateForward = (target, { render }) => {
  target.render = render
}

export const updateContext = () => {
  // nil
}

import React from 'react'

import { enterHotUpdate } from '../global/generation'
import AppContainer from '../AppContainer.dev'
import { resolveType } from './resolver'

const lazyConstructor = '_ctor'

export const updateLazy = (target, type) => {
  const ctor = type[lazyConstructor]
  if (target[lazyConstructor] !== type[lazyConstructor]) {
    // just execute `import` and RHL.register will do the job
    ctor()
  }
  if (!target[lazyConstructor].isPatchedByReactHotLoader) {
    target[lazyConstructor] = () =>
      ctor().then(m => {
        const C = resolveType(m.default)
        // chunks has been updated - new hot loader process is taking a place
        enterHotUpdate()
        return {
          default: React.forwardRef((props, ref) => (
            <AppContainer>
              <C {...props} ref={ref} />
            </AppContainer>
          )),
        }
      })
    target[lazyConstructor].isPatchedByReactHotLoader = true
  }
}

export const updateMemo = (target, { type }) => {
  target.type = resolveType(type)
}

export const updateForward = (target, { render }) => {
  target.render = render
}

export const updateContext = () => {
  // nil
}

Allow refs on lazy components


module.exports = (ctx) => ({
    plugins: {
        'postcss-lh': {},
        autoprefixer: {},
        cssnano: ctx.env === 'prod' ? {} : false
    }
});

const pkg = require('./package.json');

module.exports = (ctx) => ({
    plugins: {
        'postcss-lh': {},
        'autoprefixer': {},
        'postcss-replace': { data: pkg },
        'cssnano': ctx.env === 'prod' ? {} : false
    }
});

Replace dynamic strings with data from package.json


#!/usr/bin/env node

const chalk = require('chalk');
const yargs = require('yargs');

// ./modules
const rocketLaunch = require('./lib/modules/rocketLaunch');

var argv = yargs
  .usage('Usage: $0 <command> [options]')
  .demandCommand(1)
  .command('about', 'Info about the CLI', about)
  .command('next', 'Get next rocket launch',
    function (yargs) {
      return yargs.option('d', {
        alias: 'details',
        describe: 'Details about the next launch'
      }).option('tz', {
        alias: 'timezone',
        describe: 'Define time zone for time info'
      });
    },
    rocketLaunch.nextLaunch
  )
  .help('h')
  .alias('h', 'help')
  .argv;

function about() {
  console.log(chalk.green('Welcome to Space CLI'), '- a CLI for space information' + '\n\n' + 'Credits:' + '\n' + 'https://launchlibrary.net/ - API documentation for upcoming launches');
}

#!/usr/bin/env node

const chalk = require('chalk');
const yargs = require('yargs');

// ./modules
const rocketLaunch = require('./lib/modules/rocketLaunch');

var argv = yargs
  .usage('Usage: $0 <command> [options]')
  .demandCommand(1)
  .command('about', 'Info about the CLI', about)
  .command('next', 'Get next rocket launch',
    function (yargs) {
      return yargs.option('d', {
        alias: 'details',
        describe: 'Details about the next launch'
      }).option('tz', {
        alias: 'timezone',
        describe: 'Define time zone for time info e.g. America/New_York, Europe/Paris, Asia/Shanghai'
      });
    },
    rocketLaunch.nextLaunch
  )
  .help('h')
  .alias('h', 'help')
  .argv;

function about() {
  console.log(chalk.green('Welcome to Space CLI'), '- a CLI for space information' + '\n\n' + 'Credits:' + '\n' + 'https://launchlibrary.net/ - API documentation for upcoming launches');
}

Add example time zones to option definition


'use strict';
var gutil = require('gulp-util');
var through = require('through2');
var juice = require('juice2');

module.exports = function(opt){
    return through.obj(function (file, enc, cb) {
        opt = opt || {};

        // 'url' option is required
        // set it automatically if not provided
        opt.url = opt.url || 'file://' + file.path;

        if (file.isStream()) {
            this.emit('error', new gutil.PluginError('gulp-inline-css', 'Streaming not supported'));
            return cb();
        }

        juice.juiceContent(file.contents, opt, function(err, html) {
            if (err) {
                this.emit('error', new gutil.PluginError('gulp-inline-css', err));
            }

            file.contents = new Buffer(String(html));

            this.push(file);

            return cb();
        }.bind(this));
    });
};

'use strict';

var gutil = require('gulp-util'),
    through = require('through2'),
    juice = require('juice2');

module.exports = function(opt){
    return through.obj(function (file, enc, cb) {
        var _opt = JSON.parse(JSON.stringify(opt || {}));

        // 'url' option is required
        // set it automatically if not provided
        if (!_opt.url) {
            _opt.url = 'file://' + file.path;
        }

        if (file.isStream()) {
            this.emit('error', new gutil.PluginError('gulp-inline-css', 'Streaming not supported'));
            return cb();
        }

        juice.juiceContent(file.contents, _opt, function(err, html) {
            if (err) {
                this.emit('error', new gutil.PluginError('gulp-inline-css', err));
            }

            file.contents = new Buffer(String(html));

            this.push(file);

            return cb();
        }.bind(this));
    });
};

Fix issue with relative stylesheets across files.


var is = require('core-util-is') // added in Node 0.12

/**
 * Instrument an object or class so that anytime a method is invoked, it gets
 * logged to the console.
 *
 * @param  {function} constructor
 */
module.exports = function (constructor) {
  Object.keys(constructor).forEach(function (methodName) {
    if (!is.isFunction(constructor[methodName])) {
      return
    }

    var originalMethod = constructor[methodName]
    constructor[methodName] = function () {
      var args = Array.prototype.slice.call(arguments)
      console.log('Called: ' + methodName + '(' + args + ')')
      originalMethod.apply(null, args)
    }
  })

  var proto = constructor.prototype
  if (proto !== undefined) {
    Object.keys(proto).forEach(function (methodName) {
      var propDesc = Object.getOwnPropertyDescriptor(proto, methodName)
      if (!propDesc.configurable || ('get' in propDesc) || ('set' in propDesc) ||
          !is.isFunction(proto[methodName])) {
        return
      }

      var originalMethod = proto[methodName]
      proto[methodName] = function () {
        var args = Array.prototype.slice.call(arguments)
        console.log('Called: ' + methodName + '(' + args + ')')
        return originalMethod.apply(this, args)
      }
    })
  }
}

var is = require('core-util-is') // added in Node 0.12

/**
 * Instrument an object or class so that anytime a method is invoked, it gets
 * logged to the console.
 *
 * @param  {function} constructor
 */
module.exports = function (constructor) {
  Object.keys(constructor).forEach(function (methodName) {
    if (!is.isFunction(constructor[methodName])) {
      return
    }

    var originalMethod = constructor[methodName]
    constructor[methodName] = function () {
      var args = Array.prototype.slice.call(arguments)
      console.log('Called: ' + methodName + '(' + args + ')')
      return originalMethod.apply(null, args)
    }
  })

  var proto = constructor.prototype
  if (proto !== undefined) {
    Object.keys(proto).forEach(function (methodName) {
      var propDesc = Object.getOwnPropertyDescriptor(proto, methodName)
      if (!propDesc.configurable || ('get' in propDesc) || ('set' in propDesc) ||
          !is.isFunction(proto[methodName])) {
        return
      }

      var originalMethod = proto[methodName]
      proto[methodName] = function () {
        var args = Array.prototype.slice.call(arguments)
        console.log('Called: ' + methodName + '(' + args + ')')
        return originalMethod.apply(this, args)
      }
    })
  }
}

Return the original function value for static methods, too


var express = require('express'),
    history = require('./routes/history');

var app = express();

app.configure(function(){
  app.use(express.bodyParser());
});
app.get('/history/count', history.countAll);
app.get('/history/:id/reports', history.findByBrowser);
app.get('/history/:id', history.findById);
app.get('/history', history.findAll);
app.post('/history/', history.push);
app.get('/history/remove/all', history.removeAll);
app.get('/history/latest/:id/:since', history.getLatestStamp);
app.get('/history/latest/:id', history.getLatestStamp);
app.get('/history/all/property/:property', history.getAllProperties);

app.listen(3000);
console.log('Listening on port 3000...');

var express = require('express'),
    history = require('./routes/history');

var app = express();

app.configure(function(){
  app.use(express.bodyParser());
});
app.get('/history/count', history.countAll);
app.get('/history/:id/reports', history.findByBrowser);
app.get('/history/:id', history.findById);
app.get('/history', history.findAll);
app.post('/history/', history.push);
app.get('/history/remove/all', history.removeAll);
app.get('/history/latest/:id/:since', history.getLatestStamp);
app.get('/history/latest/:id', history.getLatestStamp);
app.get('/history/all/property/:property', history.getAllProperties);

app.listen(80);
console.log('Listening on port 80...');

Change default port to 80


'use strict';
var execFile = require('child_process').execFile;
var pify = require('pify');
var Promise = require('pinkie-promise');

module.exports = function () {
	if (process.platform !== 'darwin') {
		return Promise.reject(new Error('Only OS X systems are supported'));
	}

	var cmd = 'open';
	var args = [
		'-a',
		'ScreenSaverEngine'
	];

	return pify(execFile, Promise)(cmd, args);
};

'use strict';
var execFile = require('child_process').execFile;
var pify = require('pify');
var Promise = require('pinkie-promise');

module.exports = function () {
	if (process.platform !== 'darwin') {
		return Promise.reject(new Error('Only OS X systems are supported'));
	}

	var cmd = 'open';
	var args = [
		'/System/Library/Frameworks/ScreenSaver.framework/Versions/A/Resources/ScreenSaverEngine.app'
	];

	return pify(execFile, Promise)(cmd, args);
};

Use alternative approach to start screensaver


var fs    = require('fs'),
    spawn = require('child_process').spawn;

module.exports = {

  config: {
    binary: {
      type: "string",
      default: "/usr/local/bin/perltidy"
    }
  },

  activate: function() {
    atom.commands.add('atom-workspace', 'perltidy:tidy', function() {

      var editor = atom.workspace.getActiveTextEditor();
      var path   = atom.config.get('perltidy.binary');

      if (fs.existsSync(path)) {
        var position = editor.getCursorScreenPosition();
        perlTidy(path, editor.getText(), function (perl) {
          editor.transact(function() {
            editor.setText(perl);
            editor.getLastCursor().setScreenPosition(position);
          });
        });
      }

      else {
        editor.setText('No Perltidy found at "' + path + '".');
      }
    });
  }
};

function perlTidy(path, before, cb) {

  var after = '';
  var perltidy = spawn(path);
  perltidy.stdin.setEncoding  = 'utf-8';
  perltidy.stdout.setEncoding = 'utf-8';
  perltidy.stdin.end(before);
  perltidy.on('exit', function() {
    cb(after);
  });
  perltidy.stdout.on('data', function(chunk) {
    after += chunk;
  });
}

var fs    = require('fs'),
    path  = require('path'),
    spawn = require('child_process').spawn;

module.exports = {

  config: {
    binary: {
      type: "string",
      default: "/usr/local/bin/perltidy"
    },
    options: {
      type: "array",
      default: ["--pro=.../.perltidyrc"],
      items: {
        type: "string"
      }
    }
  },

  activate: function() {
    atom.commands.add('atom-workspace', 'perltidy:tidy', function() {

      var editor  = atom.workspace.getActiveTextEditor();
      var cwd     = path.dirname(editor.getPath());
      var binary  = atom.config.get('perltidy.binary');
      var options = atom.config.get('perltidy.options');

      if (fs.existsSync(binary)) {
        var position = editor.getCursorScreenPosition();
        perlTidy(binary, cwd, options, editor.getText(), function (perl) {
          editor.transact(function() {
            editor.setText(perl);
            editor.getLastCursor().setScreenPosition(position);
          });
        });
      }

      else {
        editor.setText('No Perltidy found at "' + path + '".');
      }
    });
  }
};

function perlTidy(binary, cwd, options, before, cb) {

  var after = '';
  var perltidy = spawn(binary, options, { cwd: cwd, stdio: 'pipe' });
  perltidy.stdin.setEncoding  = 'utf-8';
  perltidy.stdout.setEncoding = 'utf-8';
  perltidy.stdin.end(before);
  perltidy.on('exit', function() {
    cb(after);
  });
  perltidy.stdout.on('data', function(chunk) {
    after += chunk;
  });
}

Introduce cwd & options support


var fs      = require('fs');
var path    = require('path');
var sass    = require('node-sass');

module.exports = function dmpSass ($, document, done) {
  sass.render({
    file: 'assets/css/style.scss',
    outputStyle: 'compressed',
    sourceMap: false,
    success: function (result) {
      var cache = require('documark-cache')(document);
      var file = cache.fileWriteStream('sass-cache.css');
      file.end(result.css);

      $.root().append('<link rel="stylesheet" type="text/css" href="'   '">');
    },
    error: function (error) {
      console.log(error.message);
    }
  });

  done();
};

var fs      = require('fs');
var path    = require('path');
var sass    = require('node-sass');

module.exports = function dmpSass ($, document, done) {
  sass.render({
    file: 'assets/css/style.scss',
    outputStyle: 'compressed',
    sourceMap: false,
    success: function (result) {
      var cache = require('documark-cache')(document);
      var file = cache.fileWriteStream('sass-cache.css');
      file.end(result.css);

      $.root().append('<link rel="stylesheet" type="text/css" href="' + cache.filePath('sass-cache.css') + '">');
    },
    error: function (error) {
      console.log(error.message);
    }
  });

  done();
};

Add css to root element


/*
 Copyright (c) 2013, Yahoo! Inc. All rights reserved.
 Copyrights licensed under the New BSD License.
 See the accompanying LICENSE file for terms.
 */

'use strict';

var walk = require('rework-walk');

exports.prefix  = prefixSelector;
exports.replace = replaceSelector;

function prefixSelector(prefix) {
    return function (style) {
        walk(style, function (rule) {
            if (!rule.selectors) { return; }

            rule.selectors = rule.selectors.map(function (selector) {
                if (selector.match(/^(html|body)/)) {
                    return selector.replace(/^(html|body)/, prefix);
                }

                return prefix + ' ' + selector;
            });
        });
    };
}

function replaceSelector(search, replace) {
    return function (style) {
        walk(style, function (rule) {
            if (!rule.selectors) { return; }

            rule.selectors = rule.selectors.map(function (selector) {
                return selector.replace(search, replace);
            });
        });
    };
}

Add copyright to source files


/* jslint node: true */
'use strict';

var injector = require('connect-injector');

module.exports = function injectBrowserSync(browserSync) {
  var snippet = '';

  browserSync.emitter.on('service:running', function(data) {
    if (!snippet) {
      snippet = data.options.get('snippet');
    }
  });

  return injector(function(req, res) {
    var contentType = res.getHeader('content-type');
    return contentType && (contentType.toLowerCase().indexOf('text/html') >= 0);
  }, function converter(content, req, res, callback) {
    function inject() {
      var lastBody = /<\s*\/\s*body\s*>(?!(.|\n)*<\s*\/\s*body\s*>)/gi;
      var injected = content.toString().replace(lastBody, snippet + '</body>');
      callback(null, injected);
    };

    if (!snippet) {
      // We don't have the snippet from BrowserSync yet.
      // Block the response until we get it.
      browserSync.emitter.on('service:running', function(data) {
        if (!snippet) {
          snippet = data.options.get('snippet');
        }
        inject();
      });
    } else {
      inject();
    }
  });
};

/* jslint node: true */
'use strict';

var injector = require('connect-injector');

module.exports = function injectBrowserSync(browserSync, options) {
  var snippet = '';
  var options = options || {}
  var tag = ''
  var regex = /<\s*\/\s*body\s*>(?!(.|\n)*<\s*\/\s*body\s*>)/gi

  if (options.injectHead === true) {
      tag = ''
      regex = /<\/head>/gi
  }

  browserSync.emitter.on('service:running', function(data) {
    if (!snippet) {
      snippet = data.options.get('snippet');
    }
  });

  return injector(function(req, res) {
    var contentType = res.getHeader('content-type');
    return contentType && (contentType.toLowerCase().indexOf('text/html') >= 0);
  }, function converter(content, req, res, callback) {
    function inject() {
      var lastBody = regex
      var injected = content.toString().replace(lastBody, snippet + tag);
      callback(null, injected);
    };

    if (!snippet) {
      // We don't have the snippet from BrowserSync yet.
      // Block the response until we get it.
      browserSync.emitter.on('service:running', function(data) {
        if (!snippet) {
          snippet = data.options.get('snippet');
        }
        inject();
      });
    } else {
      inject();
    }
  });
};

Add options to allow script injection in head tag


var craftingrecipes = require('craftingrecipes');
var ItemPile = require('itempile');

module.exports = function(game, opts) {
  return new RecipesPlugin(game, opts);
};

function RecipesPlugin(game, opts) {
  this.craftList = new craftingrecipes.RecipeList();
  this.thesaurus = new craftingrecipes.CraftingThesaurus();
}

RecipesPlugin.prototype.register = function(recipe) {
  return this.craftList.register(recipe);
};

RecipesPlugin.prototype.registerAmorphous = function(ingredients, result) {
  return this.register(new craftingrecipes.AmorphousRecipe(ingredients, ItemPile.fromArrayIfArray(result)));
};

RecipesPlugin.prototype.registerPositional = function(ingredients, result) {
  return this.register(new craftingrecipes.PositionalRecipe(ingredients, ItemPile.fromArrayIfArray(result)));
};

RecipesPlugin.prototype.find = function(inventory) {
  return this.craftList.find(inventory);
};

RecipesPlugin.prototype.craft = function(inventory) {
  return this.craftList.craft(inventory);
};

RecipesPlugin.prototype.registerSmelting = function(input, output) {

};

RecipesPlugin.prototype.smelted = function(input) {
};

var craftingrecipes = require('craftingrecipes');
var ItemPile = require('itempile');

module.exports = function(game, opts) {
  return new RecipesPlugin(game, opts);
};

function RecipesPlugin(game, opts) {
  this.craftList = new craftingrecipes.RecipeList();
  this.smeltMap = {};
  this.thesaurus = new craftingrecipes.CraftingThesaurus();
}

RecipesPlugin.prototype.register = function(recipe) {
  return this.craftList.register(recipe);
};

RecipesPlugin.prototype.registerAmorphous = function(ingredients, result) {
  return this.register(new craftingrecipes.AmorphousRecipe(ingredients, ItemPile.fromArrayIfArray(result)));
};

RecipesPlugin.prototype.registerPositional = function(ingredients, result) {
  return this.register(new craftingrecipes.PositionalRecipe(ingredients, ItemPile.fromArrayIfArray(result)));
};

RecipesPlugin.prototype.find = function(inventory) {
  return this.craftList.find(inventory);
};

RecipesPlugin.prototype.craft = function(inventory) {
  return this.craftList.craft(inventory);
};

RecipesPlugin.prototype.registerSmelting = function(input, output) {
  if (input in this.craftList)
    console.log('WARNING: voxel-recipes registerSmelting overwriting recipes '+input+' -> '+output); // TODO: do we care?

  this.craftList[input] = ItemPile.fromArrayIfArray(output);
};

RecipesPlugin.prototype.smelt = function(input) {
  if (!input || !input.item) return undefined;

  var output = this.craftList[input.item]; // TODO: smelting inputs of different stack sizes? (vs always 1)
  return output ? output.clone() : undefined;
};

Add smelting recipes support, for voxel-furnace


'use strict'
const glob = require('glob')
const prependFile = require('prepend-file')
const pkg = require(`${process.cwd()}/package.json`)

function banner (options = {}) {
	options.name = options.name || pkg.name || 'unknown'
	options.tag = options.tag || pkg.version || '0.0.0'
	options.homepage = options.homepage || pkg.homepage || `https://npm.com/${options.name}`
	options.license = options.license || pkg.license
	options.author = options.author || pkg.author.split('<')[0].trim() || ''
	options.year = options.year || new Date().getFullYear()

	const template = options.template || `/*!
  * ${options.name.charAt(0).toUpperCase() + options.name.slice(1)} v${options.tag}
  * ${options.homepage}
  *
  * Copyright (c) ${options.year} ${options.author}
  *${options.license ? ` Licensed under the ${options.license} license\n *` : ''}/\n
`

	if (!options.source) {
		throw new Error(`File not found!`)
	} else {
		glob(options.source, (err, files) => {
			if (err) throw err
			files.map(file => prependFile.sync(file, template))
			process.exit(0)
		})
	}
}

module.exports = banner

'use strict'
const glob = require('glob')
const prependFile = require('prepend-file')
const pkg = require(`${process.cwd()}/package.json`)

const getAuthorName = value => {
	if (typeof value === 'string') return value.split('<')[0].trim()
	if (value instanceof Object && typeof value.name === 'string') return value.name
	return ''
}

function banner (options = {}) {
	options.name = options.name || pkg.name || 'unknown'
	options.tag = options.tag || pkg.version || '0.0.0'
	options.homepage = options.homepage || pkg.homepage || `https://npm.com/${options.name}`
	options.license = options.license || pkg.license
	options.author = options.author || getAuthorName(pkg.author)
	options.year = options.year || new Date().getFullYear()

	const template = options.template || `/*!
  * ${options.name.charAt(0).toUpperCase() + options.name.slice(1)} v${options.tag}
  * ${options.homepage}
  *
  * Copyright (c) ${options.year} ${options.author}
  *${options.license ? ` Licensed under the ${options.license} license\n *` : ''}/\n
`

	if (!options.source) {
		throw new Error(`File not found!`)
	} else {
		glob(options.source, (err, files) => {
			if (err) throw err
			files.map(file => prependFile.sync(file, template))
			process.exit(0)
		})
	}
}

module.exports = banner

Add support to author field can be object or string


exports = module.exports = function (options) {
  return function clone(style) {
    return new Clone(style, options || {})
  }
}

function Clone (style, options) {
  var regexp = options.regexp || /^(clone|copy)?$/i
  var rules = style.rules;
  rules.forEach(function (rule) {
    if (rule.type === 'media') {
      return rule.rules.forEach(function (rrule) {
        processing(rules, regexp, rrule);
      });
    }
    if (rule.type !== 'rule') {
      return;
    }
    processing(rules, regexp, rule);
  });
}

function processing (rules, regexp, rule) {
  var clones = getClones(regexp, rule.declarations);
  if (clones.length !== 0) {
    rule.declarations = getProperties(rules, clones).concat(rule.declarations);
  }
}

function getClones (regexp, declarations) {
  var clones = [], i, dec;
  for (i = 0; i < declarations.length; i++) {
    dec = declarations[i];
    if (regexp.test(dec.property)) {
      clones.push(dec.value);
      declarations.splice(i--, 1);
    }
  }
  return clones;
}

function getProperties (rules, selectors) {
  var declarations = [];
  rules.forEach(function (rule) {
    if (rule.selectors && rule.selectors.length > 0) {
      selectors.forEach(function (selector) {
        if (rule.selectors.indexOf(selector) !== -1) {
          declarations = declarations.concat(rule.declarations);
        }
      });
    }
  });
  return declarations;
}

exports = module.exports = function (options) {
  return function clone(style) {
    return new Clone(style, options || {})
  }
}

function Clone (style, options) {
  var regexp = options.regexp || /^(clone|copy)?$/i
  var rules = style.rules;
  rules.forEach(function (rule) {
    if (rule.type === 'media') {
      return rule.rules.forEach(function (rrule) {
        processing(rules, regexp, rrule);
      });
    }
    if (rule.type === 'rule') {
      processing(rules, regexp, rule);
    }
  });
}

function processing (rules, regexp, rule) {
  var clones = getClones(regexp, rule.declarations);
  rule.declarations = getProperties(rules, clones)
    .concat(rule.declarations)
    .filter(function (dec) {
      return !regexp.test(dec.property);
    });
}

function getClones (regexp, declarations) {
  return declarations.filter(function (dec) {
    return regexp.test(dec.property);
  }).map(function (dec) {
    return dec.value;
  })
}

function getProperties (rules, selectors) {
  var declarations = [];
  rules.filter(function (rule) {
    return rule.selectors && rule.selectors.length > 0;
  }).forEach(function (rule) {
    selectors.filter(function (selector) {
      return rule.selectors.indexOf(selector) !== -1;
    }).forEach(function (selector) {
      declarations = declarations.concat(rule.declarations);
    });
  });
  return declarations;
}

Refactor to more functional style


'use strict';

var Filter = require('broccoli-filter');
var transform = require('coffee-react-transform');

module.exports = CjsxFilter;

CjsxFilter.prototype = Object.create(Filter.prototype);
CjsxFilter.prototype.constructor = CjsxFilter;

function CjsxFilter (inputTree, options) {
  if (!(this instanceof CjsxFilter)){
    return new CjsxFilter(inputTree, options);
  }

  this.inputTree = inputTree;
  this.options = options || {};
  if (this.options.extensions) {
    this.extensions = options.extensions;
  }
}

CjsxFilter.prototype.extensions = ['cjsx'];
CjsxFilter.prototype.targetExtension = 'coffee';

CjsxFilter.prototype.processString = function (string) {
  var result = transform(string);

  return result;
};

'use strict';

var Filter = require('broccoli-filter');
var transform = require('coffee-react-transform');

module.exports = CjsxFilter;

CjsxFilter.prototype = Object.create(Filter.prototype);
CjsxFilter.prototype.constructor = CjsxFilter;

function CjsxFilter (inputTree, options) {
  if (!(this instanceof CjsxFilter)){
    return new CjsxFilter(inputTree, options);
  }

  Filter.call(this, inputTree, options)
  this.options = options || {};
}

CjsxFilter.prototype.extensions = ['cjsx'];
CjsxFilter.prototype.targetExtension = 'coffee';

CjsxFilter.prototype.processString = function (string) {
  var result = transform(string);

  return result;
};

Call broccoli-filter's constructor (and be more future proof)


var NotificationsController = SingleModelController.createComponent("NotificationsController");

NotificationsController.defineAlias("model", "notifications");

NotificationsController.defineMethod("updateView", function () {
  if (!this.view) return;

  var bottom = 0;
  this.notifications.notifications = this.notifications.notifications.filter(function (notification) {
    var element = this.view.querySelector("[data-ica-notification-id='{0}']".format(notification.componentId));

    // Check existing element
    if (element) {
      element.style.bottom = bottom + "px";
    } else {
      // Create new view

      // Match controller
      var Controller;
      switch (notification.constructor) {
      case BasicNotification: Controller = BasicNotificationController; break;
      case ProgressNotification: Controller = ProgressNotificationController; break;
      case XHRProgressNotification: Controller = XHRProgressNotificationController; break;
      default:
        console.warn("Unhandled item:", notification.constructor);
        return false;
      }

      // Create view
      var fragment = Controller.createViewFragment();
      element = fragment.querySelector(".notification");
      element.style.bottom = bottom + "px";
      this.view.appendChild(fragment);
      new Controller(notification, element).componentOf = this;
    }

    bottom += element.offsetHeight + 8; // 16 px margin top & bottom

    return true;
  }.bind(this));
});

var NotificationsController = SingleModelController.createComponent("NotificationsController");

NotificationsController.defineAlias("model", "notifications");

NotificationsController.defineMethod("updateView", function () {
  if (!this.view) return;

  var bottom = 0;
  for (let notification of this.notifications.notifications) {
    var element = this.view.querySelector("[data-ica-notification-id='{0}']".format(notification.componentId));

    // Check existing element
    if (element) {
      element.style.bottom = bottom + "px";
    } else {
      // Create new view

      // Match controller
      var Controller;
      switch (notification.constructor) {
      case BasicNotification: Controller = BasicNotificationController; break;
      case ProgressNotification: Controller = ProgressNotificationController; break;
      case XHRProgressNotification: Controller = XHRProgressNotificationController; break;
      default:
        console.warn("Unhandled item:", notification.constructor);
        continue;
      }

      // Create view
      var fragment = Controller.createViewFragment();
      element = fragment.querySelector(".notification");
      element.style.bottom = bottom + "px";
      this.view.appendChild(fragment);
      new Controller(notification, element).componentOf = this;
    }

    bottom += element.offsetHeight + 8; // 16 px margin top & bottom
  }
});

Use for-loop rather than the filter method


var socket = io('/push-it');
var fingerprint2str;
var vid = document.getElementById('bigvid');
var bg = document.getElementsByClassName('push-it')[0];
var clients = [];

fingerprint2str = localStorage.getItem('fingerprint2');
var uri = document.createElement('a');
uri.href = document.URL;

if (bg !== null) {
    bg.addEventListener('click', function () {
        resetVid();
    }, false);
}

function resetVid() {
    vid.pause();
    vid.currentTime = 0;
    vid.muted = false;
    vid.style.visibility = "inherit";
}

socket.on('connect', function () {
    console.log('Firing. Room: %s', uri.pathname);
    if (!localStorage.getItem('fingerprint2')) {
        console.log('No Fingerprint found. Setting...');
        new Fingerprint2().get(function (result) {
            fingerprint2str = result;
            localStorage.setItem('fingerprint2', result);
            socket.emit('client connected', {
                'fp2str': fingerprint2str,
                'room': uri.pathname
            });
        });
    } else {
        socket.emit('client connected', {
            'fp2str': fingerprint2str,
            'room': uri.pathname
        });
    }
});

socket.on('disconnect', function () {
});

socket.on('push it', function (data) {
    console.log('Pushed.');
    resetVid();
    vid.play();
});

socket.on('clients update', function (data) {
    console.log('Clients:');
    console.log(data);
});

var socket = io('/push-it');
var fingerprint2str;
var vid = document.getElementById('bigvid');
var bg = document.getElementsByClassName('push-it')[0];
var clients = [];

fingerprint2str = localStorage.getItem('fingerprint2');
var uri = document.createElement('a');
uri.href = document.URL;

if (bg !== null) {
    bg.addEventListener('click', function () {
        resetVid();
    }, false);
}

function resetVid() {
    vid.pause();
    vid.currentTime = 0;
    vid.muted = false;
    vid.style.visibility = "inherit";
}

socket.on('connect', function () {
    console.log('Firing. Room: %s', uri.pathname);
    if (!localStorage.getItem('fingerprint2')) {
        console.log('No Fingerprint found. Setting...');
        new Fingerprint2().get(function (result) {
            fingerprint2str = result;
            localStorage.setItem('fingerprint2', result);
            socket.emit('client connected', {
                'fp2str': fingerprint2str,
                'room': uri.pathname
            });
        });
    } else {
        socket.emit('client connected', {
            'fp2str': fingerprint2str,
            'room': uri.pathname
        });
    }
});

socket.on('push it', function (data) {
    console.log('Pushed.');
    resetVid();
    vid.play();
});

socket.on('clients update', function (data) {
    console.log('Clients:');
    console.log(data);
});

Remove disconnect binding from client


export const DISCUSSION_NOTE = 'DiscussionNote';
export const DIFF_NOTE = 'DiffNote';
export const DISCUSSION = 'discussion';
export const NOTE = 'note';
export const SYSTEM_NOTE = 'systemNote';
export const COMMENT = 'comment';
export const OPENED = 'opened';
export const REOPENED = 'reopened';
export const CLOSED = 'closed';
export const EMOJI_THUMBSUP = 'thumbsup';
export const EMOJI_THUMBSDOWN = 'thumbsdown';
export const ISSUE_NOTEABLE_TYPE = 'issue';
export const EPIC_NOTEABLE_TYPE = 'epic';
export const MERGE_REQUEST_NOTEABLE_TYPE = 'merge_request';
export const UNRESOLVE_NOTE_METHOD_NAME = 'delete';
export const RESOLVE_NOTE_METHOD_NAME = 'post';

export const NOTEABLE_TYPE_MAPPING = {
  Issue: ISSUE_NOTEABLE_TYPE,
  MergeRequest: MERGE_REQUEST_NOTEABLE_TYPE,
  Epic: EPIC_NOTEABLE_TYPE,
};

Add map for supported noteable types


'use strict';
const path = require('path');
const nodeExternals = require('webpack-node-externals');

module.exports = {
  entry: {
    authorizer: './lambda_functions/authorizer/authorizer.js',
    'get-session': './lambda_functions/get-session/getSession.js'
  },
  target: 'node',
  module: {
    loaders: [
      {
        enforce: "pre",
        test: /\.js$/,
        loader: "eslint-loader",
        exclude: /node_modules/
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        include: __dirname,
        exclude: /node_modules/,
        query: {
          presets: ['es2015', 'stage-0']
        }
      }
    ]
  },
  babel: {
    presets: ["es2015"],
    env: {
      test: {
        plugins: ["istanbul"]
      }
    }
  },
  eslint: {
    outputReport: {
      filePath: 'checkstyle.xml',
      formatter: require('eslint/lib/formatters/checkstyle')
    }
  },
  output: {
    libraryTarget: 'commonjs',
    path: path.join(__dirname, '.webpack'),
    filename: '[name].js'
  },
  resolve: {
    root: path.resolve(__dirname),
    alias: {
      lib: 'lib'
    },
    extensions: ['', '.js', '.jsx']
  },
  externals: [nodeExternals()]
};

'use strict';
const path = require('path');
const nodeExternals = require('webpack-node-externals');

module.exports = {
  entry: {
    authorizer: './lambda_functions/authorizer/authorizer.js',
    'get-session': './lambda_functions/get-session/getSession.js'
  },
  target: 'node',
  module: {
    loaders: [
      {
        enforce: "pre",
        test: /\.js$/,
        loader: "eslint-loader",
        exclude: /node_modules/
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        include: __dirname,
        exclude: /node_modules/,
        query: {
          presets: ['es2015', 'stage-0']
        }
      }
    ]
  },
  babel: {
    presets: ["es2015"],
    env: {
      test: {
        plugins: ["istanbul"]
      }
    }
  },
  eslint: {
    outputReport: {
      filePath: 'eslint.html',
      formatter: require('eslint/lib/formatters/html')
    }
  },
  output: {
    libraryTarget: 'commonjs',
    path: path.join(__dirname, '.webpack'),
    filename: '[name].js'
  },
  resolve: {
    root: path.resolve(__dirname),
    alias: {
      lib: 'lib'
    },
    extensions: ['', '.js', '.jsx']
  },
  externals: [nodeExternals()]
};

Change eslint formatter to HTML instead of checkstyle


module.exports = {
  entry: './src/app.js',
  output: {
    path: './dist',
    filename: 'build.js'
  }
}

module.exports = {
  entry: './src/app.js',
  output: {
    path: './dist',
    filename: 'build.js'
  },
  devtool: 'source-map'
}

Add support for source maps


!(function( global ) {

  // NEX<->CRX support set up
  var nexAPIStubs = ['app', 'extension', 'windows', 'tabs', 'browserAction', 'contextMenus', 'i18n', 'webRequest'];
  if(!global.chrome) {
    global.chrome = {};
  }
  for(var i = 0, l = nexAPIStubs.length; i < l; i++) {
    global.chrome[ nexAPIStubs[ i ] ] = global.chrome[ nexAPIStubs[ i ] ] || global.navigator[ nexAPIStubs[ i ] ] || {};
  }

  var Opera = function() {};

  Opera.prototype.REVISION = '1';

  Opera.prototype.version = function() {
    return this.REVISION;
  };

  Opera.prototype.buildNumber = function() {
    return this.REVISION;
  };

  Opera.prototype.postError = function( str ) {
    console.log( str );
  };

  var opera = global.opera || new Opera();

  var manifest = chrome.app.getDetails(); // null in injected scripts / popups

  navigator.browserLanguage=navigator.language; //Opera defines both, some extensions use the former

  var isReady = false;

  var _delayedExecuteEvents = [
    // Example:
    // { 'target': opera.extension, 'methodName': 'message', 'args': event }
  ];

  function addDelayedEvent(target, methodName, args) {
    if(isReady) {
      target[methodName].apply(target, args);
    } else {
      _delayedExecuteEvents.push({
        "target": target,
        "methodName": methodName,
        "args": args
      });
    }
  };

!(function( global ) {

  var Opera = function() {};

  Opera.prototype.REVISION = '1';

  Opera.prototype.version = function() {
    return this.REVISION;
  };

  Opera.prototype.buildNumber = function() {
    return this.REVISION;
  };

  Opera.prototype.postError = function( str ) {
    console.log( str );
  };

  var opera = global.opera || new Opera();

  var manifest = chrome.app.getDetails(); // null in injected scripts / popups

  navigator.browserLanguage=navigator.language; //Opera defines both, some extensions use the former

  var isReady = false;

  var _delayedExecuteEvents = [
    // Example:
    // { 'target': opera.extension, 'methodName': 'message', 'args': event }
  ];

  function addDelayedEvent(target, methodName, args) {
    if(isReady) {
      target[methodName].apply(target, args);
    } else {
      _delayedExecuteEvents.push({
        "target": target,
        "methodName": methodName,
        "args": args
      });
    }
  };

Remove defunct NEX aliasing from OEX shim (see: DNA-2416)


'use strict';

module.exports = input => {
  const regex = /^[A-Za-z-]+$/g;

  if (!input) {
    return 'You must provide an input';
  }

  return regex.test(input) || "Please use only letters, '-' and no spaces";
};

'use strict';

module.exports = (input, allowSnakeCase = false) => {
  const regex = allowSnakeCase ? /^[A-Za-z-|_]+$/g : /^[A-Za-z-]+$/g;

  if (!input) {
    return "You must provide an input";
  }

  return regex.test(input) || "Please use only letters, '-' and no spaces";
};

Add snake_case param for validating generate input


import gql from "graphql-tag";

class IndicatorRepository {
  static getListPage(pageNumber, pageSize) {
    return gql`{
      allIndicators{
        nodes {
          id
          name
          description
          executionOrder
          flagActive
          createdDate
          updatedDate
          indicatorTypeId
        }
      }
    }`
  }

  static getFormDropdownData() {
    return gql`
      {
        allIndicatorTypes {
          nodes {
            id
            name
          }
        }
        allIndicatorGroups {
          nodes {
            id
            name
          }
        }
      }`
  }

  static insert() {
    return gql`
      mutation addNewIndicator($indicator: IndicatorInput!) {
        createIndicator(input: { indicator: $indicator }) {
          indicator {
            id
            name
            description
          }
        }
      }`
  }

  static getIndicatorToUpdate(id) {
      return gql`
    indicatorById(id:` + id + `) {
          id
          name
          description
          executionOrder
          flagActive
          createdDate
          updatedDate
          indicatorTypeId
      }
    }`
  }

    static update() {
        return gql`
      mutation updateIndicator($id: Int!, $indicatorPatch: IndicatorPatch!) {
        updateIndicatorById(input: {id: $id, indicatorPatch: $indicatorPatch}) {
          indicator {
            id
          }
        }
      }`
    }
}

export default IndicatorRepository;

import gql from "graphql-tag";

class IndicatorRepository {
  static getListPage(pageNumber, pageSize) {
    return gql`
      {
        allIndicators{
          nodes {
            id
            name
            indicatorTypeByIndicatorTypeId {
              name
            }
            indicatorGroupByIndicatorGroupId {
              name
            }
            executionOrder
            flagActive
            updatedDate
          }
        }
      }
    `
  }

  static getFormDropdownData() {
    return gql`
      {
        allIndicatorTypes {
          nodes {
            id
            name
          }
        }
        allIndicatorGroups {
          nodes {
            id
            name
          }
        }
      }
    `
  }

  static insert() {
    return gql`
      mutation addNewIndicator($indicator: IndicatorInput!) {
        createIndicator(input: { indicator: $indicator }) {
          indicator {
            id
            name
            description
          }
        }
      }
    `
  }

  static getIndicatorToUpdate(id) {
    return gql`
      {
        indicatorById(id:` + id + `) {
          id
          name
          description
          executionOrder
          flagActive
          createdDate
          updatedDate
          indicatorTypeId
        }
      }
    `
  }

  static update() {
    return gql`
      mutation updateIndicator($id: Int!, $indicatorPatch: IndicatorPatch!) {
        updateIndicatorById(input: {id: $id, indicatorPatch: $indicatorPatch}) {
          indicator {
            id
          }
        }
      }
    `
  }
}

export default IndicatorRepository;

Modify indicator list query. Format indicator queries. Corrected missing { for getIndicatorToUpdate


'use strict'

export default class LodashWrapper {
  constructor (_) {
    this.steps = []
    let step = 1

    const record = (name, args, result) => {
      if (name === 'chain' || typeof (name) === 'undefined') {
        return
      }

      this.steps.push({
        step: step++,
        funcName: name,
        args: JSON.stringify(args, null, 2),
        result: JSON.stringify(result, null, 2)
      })
    }

    const availableFunctions = _.keys(_)

    const handler = {
      get: (original, propertyName) => {
        if (!availableFunctions.includes(propertyName)) {
          return original[propertyName]
        }

        // console.info(`Getting ${propertyName}`)
        original[propertyName].dexterLabFuncName = propertyName
        return new Proxy(original[propertyName], handler)
      },

      apply: (original, thisArg, args) => {
        // console.info(`Calling ${original.dexterLabFuncName}`)
        const result = original.apply(thisArg, args)

        if (result.__wrapped__) {
          record(original.dexterLabFuncName, args, result.value())
          return new Proxy(result, handler)
        }

        record(original.dexterLabFuncName, args, result)
        return result
      }
    }

     // let the Inception begins :-)
    this.lodash = new Proxy(_.runInContext(), handler)
  }

  get stats () {
    return this.steps
  }

  resetStats () {
    this.steps = []
  }
}

'use strict'

export default class LodashWrapper {
  constructor (_) {
    this.steps = []
    let step = 1

    const record = (name, isChained, args, result) => {
      if (name === 'chain' || typeof (name) === 'undefined') {
        return
      }

      this.steps.push({
        step: step++,
        funcName: name,
        args: JSON.stringify(args, null, 2),
        isChained,
        result: JSON.stringify(result, null, 2)
      })
    }

    const availableFunctions = _.keys(_)

    const handler = {
      get: (original, propertyName) => {
        if (!availableFunctions.includes(propertyName)) {
          return original[propertyName]
        }

        // console.info(`Getting ${propertyName}`)
        original[propertyName].dexterLabFuncName = propertyName
        return new Proxy(original[propertyName], handler)
      },

      apply: (original, thisArg, args) => {
        // console.info(`Calling ${original.dexterLabFuncName}`)
        const result = original.apply(thisArg, args)

        if (result.__wrapped__) {
          record(original.dexterLabFuncName, true, args, result.value())
          return new Proxy(result, handler)
        }

        record(original.dexterLabFuncName, false, args, result)
        return result
      }
    }

     // let the Inception begins :-)
    this.lodash = new Proxy(_.runInContext(), handler)
  }

  get stats () {
    return this.steps
  }

  resetStats () {
    this.steps = []
  }
}

Add flag indicating method comes from chain execution


/*
Copyright (C) 2010, Oleg Efimov <efimovov@gmail.com>

See license text in LICENSE file
*/

/*
> mysql -u root
CREATE DATABASE test DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
GRANT ALL ON test.* TO test@localhost IDENTIFIED BY "";
*/

exports.getConfig = function (factor) {
  var cfg = {
    // Database connection settings
    host: "localhost",
    user: "test",
    password: "",
    database: "test",
    test_table: "test_table",

    // Benchmarks parameters
    escape_count: 1000000 * factor,
    string_to_escape: "str\\str\"str\'str\x00str",
    reconnect_count: 10000 * factor,
    insert_rows_count: 100000 * factor,

    // Delay before assertion check (ms)
    delay_before_select: 1 * 1000,

    // Run sync functions if async exists?
    do_not_run_sync_if_async_exists: true
  };

  cfg.create_table_query = "CREATE TABLE " + cfg.test_table +
                           " (alpha INTEGER, beta VARCHAR(128), pi FLOAT) " +
                           "TYPE=MEMORY;";

  cfg.insert_query = "INSERT INTO " + cfg.test_table +
                     " VALUES (1, 'hello', 3.141);";

  cfg.selected_row_example = {alpha: 1, beta: 'hello', pi: 3.141};

  return cfg;
};

/*
Copyright (C) 2010, Oleg Efimov <efimovov@gmail.com>

See license text in LICENSE file
*/

/*
> mysql -u root
CREATE DATABASE test DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
GRANT ALL ON test.* TO test@localhost IDENTIFIED BY "";
*/

exports.getConfig = function (factor) {
  var cfg = {
    // Database connection settings
    host: "127.0.0.1",
    user: "test",
    password: "",
    database: "test",
    test_table: "test_table",

    // Benchmarks parameters
    escape_count: 1000000 * factor,
    string_to_escape: "str\\str\"str\'str\x00str",
    reconnect_count: 10000 * factor,
    insert_rows_count: 100000 * factor,

    // Delay before assertion check (ms)
    delay_before_select: 1 * 1000,

    // Run sync functions if async exists?
    do_not_run_sync_if_async_exists: true
  };

  cfg.create_table_query = "CREATE TABLE " + cfg.test_table +
                           " (alpha INTEGER, beta VARCHAR(128), pi FLOAT) " +
                           "TYPE=MEMORY;";

  cfg.insert_query = "INSERT INTO " + cfg.test_table +
                     " VALUES (1, 'hello', 3.141);";

  cfg.selected_row_example = {alpha: 1, beta: 'hello', pi: 3.141};

  return cfg;
};

Use IP instead of hostname in connection settings


$(function(){
  $('input').on("focus", function(){
     $(this).siblings('label').addClass("is-focused");
  });
  $('input').on("blur", function(){
    $(this).siblings('label').removeClass("is-focused");
    if($(this).val() ) {
      $(this).siblings('label').addClass('is-dirty');
    } else {
      $(this).siblings('label').removeClass('is-dirty');
    }
  });
});

$(function(){
  $('input').on("focus", function(){
     $(this).siblings('label').addClass("is-focused");
  });
  $('input').on("blur", function(){
    $(this).siblings('label').removeClass("is-focused");
    if($(this).val() ) {
      $(this).siblings('label').addClass('is-dirty');
    } else {
      $(this).siblings('label').removeClass('is-dirty');
    }
  });
  $('input').each(function(){
    if($(this).val() ) {
      $(this).siblings('label').addClass('is-dirty');
    } else {
      $(this).siblings('label').removeClass('is-dirty');
    }
  });
});

Check for content in form fields when they load


import resolve from 'rollup-plugin-node-resolve';
import common from 'rollup-plugin-commonjs';
import json from 'rollup-plugin-json';
import replace from 'rollup-plugin-re';
import typescript from 'rollup-plugin-typescript';

export default {
  input: 'lib/index.ts',
  output: {
    file: 'dist/bundle.js',
    format: 'cjs'
  },
  plugins: [
    replace({
      patterns: [
        {
          match: /formidable(\/|\\)lib/,
          test: 'if (global.GENTLY) require = GENTLY.hijack(require);',
          replace: '',
        },
        {
          match: /analytics-node\/index.js/,
          test: './package',
          replace: './package.json'
        }
      ]
    }),
    typescript({
      typescript: require('typescript')
    }),
    common({
      include: 'node_modules/**'
    }),
    json(),
    resolve(),
  ]
};

import resolve from 'rollup-plugin-node-resolve';
import common from 'rollup-plugin-commonjs';
import json from 'rollup-plugin-json';
import replace from 'rollup-plugin-re';
import typescript from 'rollup-plugin-typescript';

export default {
  input: 'lib/index.ts',
  output: {
    file: 'dist/bundle.js',
    format: 'cjs'
  },
  external: ['https', 'atom', 'dgram', 'fs', 'child_process', 'crypto', 'path', 'os'],
  plugins: [
    replace({
      patterns: [
        {
          match: /formidable(\/|\\)lib/,
          test: 'if (global.GENTLY) require = GENTLY.hijack(require);',
          replace: '',
        },
        {
          match: /analytics-node\/index.js/,
          test: './package',
          replace: './package.json'
        }
      ]
    }),
    typescript({
      typescript: require('typescript')
    }),
    common({
      include: 'node_modules/**'
    }),
    json(),
    resolve(),
  ]
};

Add externals to stop rollup unresolved dependency warnings


var SandwichTime = (function () {

  var level;

  function Slab(width, height, upperLeft, paint) {
    var width, height, upperLeft, paint;
    this.width = width;
    this.height = height;
    this.upperLeft = upperLeft;
    this.paint = paint;
  }

  function Tower(slabs) {
    var numSlabs,
        slabs;
    this.numSlabs = slabs.length;
    this.slabs = slabs;
  }

  function Grid(width, height) {
    this.width = width;
    this.height = height;
  }

  function Level(grid, towers) {
    this.grid = grid;
    this.towers = towers;
  }

  function makeRandomLevel(width, height) {
    var grid = new Grid(width, height),
        towers = [
        ];
    return new Level(grid, towers);
  }

  function load() {
    level = makeRandomLevel(500, 800);
    console.log('ready');
  }

  return {
    load: load
  };
})();

window.onload = SandwichTime.load;

var SandwichTime = (function () {

  var level;

  function Slab(width, height, upperLeft, paint) {
    var width, height, upperLeft, paint;
    this.width = width;
    this.height = height;
    this.upperLeft = upperLeft;
    this.paint = paint;
  }

  function Tower(slabs) {
    var numSlabs,
        slabs;
    this.numSlabs = slabs.length;
    this.slabs = slabs;
  }

  function makeRandomTower(grid) {
    var slabs = [],
        numSlabs = 3,
        width = 5 + Math.floor(grid / 10 * Math.random()),
        height = 4,
        x = 10, y = 10,
        i, slab;
    for (i = 0; i < numSlabs; ++i) {
      slab = new Slab(width, 4, { x: x + i * 30, y: y }, null);
      slabs.push(slab);
    }
    return new Tower(slabs);
  }

  function Grid(width, height) {
    this.width = width;
    this.height = height;
  }

  function Level(grid, towers) {
    this.grid = grid;
    this.towers = towers;
  }

  function makeRandomLevel(width, height) {
    var grid = new Grid(width, height),
        towers = [],
        numTowers = 1,
        tower, i;
    for (i = 0; i < numTowers; ++i) {
      tower = makeRandomTower(grid);
      towers.push(tower);
    }
    return new Level(grid, towers);
  }

  function load() {
    level = makeRandomLevel(500, 800);
    console.log('ready');
  }

  return {
    load: load
  };
})();

window.onload = SandwichTime.load;

Make a partially random tower


/* eslint-disable import/no-dynamic-require,global-require */

import fs from 'fs';
import path from 'path';
import log from 'fancy-log';
import dotenv from 'dotenv';
import config from './lib/config';

/**
 * Update `cwd` if `package.json` is a symlink.
 */
const packageLocation = fs.realpathSync(path.resolve(process.cwd(), 'package.json'));
const realPath = path.dirname(packageLocation);
if (process.cwd() !== realPath) {
  try {
    process.chdir(realPath);
  } catch (error) {
    log.error(`Unable to switch to symbolic directory: ${error}`);
    process.exit(1);
  }
}

/**
 * Load environment variables from `.env`.
 */
dotenv.config({ path: config.get('dotenv.file') || process.cwd() });

/**
 * Gulp tasks are defined in separate files in the tasks folder.
 */
const taskFolder = path.join(__dirname, 'tasks');
fs.readdirSync(taskFolder)
  .filter(name => /(\.(js)$)/i.test(path.extname(name)))
  .forEach(task => require(path.join(taskFolder, task)));

/**
 * Custom `SIGINT` listener to exit process.
 */
process.on('SIGINT', e => process.exit(1));

/* eslint-disable import/no-dynamic-require,global-require */

import fs from 'fs';
import path from 'path';
import log from 'fancy-log';
import dotenv from 'dotenv';
import config from './lib/config';

/**
 * Update `cwd` if `package.json` is a symlink.
 */
const packageLocation = fs.realpathSync(path.resolve(process.cwd(), 'package.json'));
const realPath = path.dirname(packageLocation);
if (process.cwd() !== realPath) {
  try {
    process.chdir(realPath);
  } catch (error) {
    log.error(`Unable to switch to symbolic directory: ${error}`);
    process.exit(1);
  }
}

/**
 * Load environment variables from `.env`.
 */
dotenv.config({ path: config.get('dotenv.file') || `${process.cwd()}/.env` });

/**
 * Gulp tasks are defined in separate files in the tasks folder.
 */
const taskFolder = path.join(__dirname, 'tasks');
fs.readdirSync(taskFolder)
  .filter(name => /(\.(js)$)/i.test(path.extname(name)))
  .forEach(task => require(path.join(taskFolder, task)));

/**
 * Custom `SIGINT` listener to exit process.
 */
process.on('SIGINT', e => process.exit(1));

Fix incorrect dotenv path fallback


var utils = require('./utils');
var applicative = require('./applicative');
var ownPropFrom = utils.ownPropFrom;
var isOwnFunction = utils.isOwnFunction;

var derivables = {
  map: function(f) {
    var m = this;
    return m.chain(function(a) { return m.of(f(a)); });
  },
  ap: function(other) {
    return this.chain(function(f) { return other.map(f); });
  }
};

function monad(type, definition) {
  if (!isOwnFunction(definition, 'chain'))
    throw new Error("You need to implement the method `chain`");
  type.prototype.chain = definition.chain;

  var newDefinition = {
    of: definition.of,
    map: ownPropFrom(definition, 'map') || derivables.map,
    ap: ownPropFrom(definition, 'ap') || derivables.ap
  };

  applicative(type, newDefinition);
}

monad.map = applicative.map;
monad.ap = applicative.ap;
monad.pure = applicative.pure;
module.exports = monad;

monad(Array, {
  chain: function(f) {
    return this.map(function(x) { return f(x); })
        .reduce(function(list, x) { return list.concat(x); }, []);
  }
});

var utils = require('./utils');
var applicative = require('./applicative');
var ownPropFrom = utils.ownPropFrom;
var isOwnFunction = utils.isOwnFunction;

var derivables = {
  map: function(f) {
    var m = this;
    return m.chain(function(a) { return m.constructor.of(f(a)); });
  },
  ap: function(other) {
    return this.chain(function(f) { return other.map(f); });
  }
};

function monad(type, definition) {
  if (!isOwnFunction(definition, 'chain'))
    throw new Error("You need to implement the method `chain`");
  type.prototype.chain = definition.chain;

  var newDefinition = {
    of: definition.of,
    map: ownPropFrom(definition, 'map') || derivables.map,
    ap: ownPropFrom(definition, 'ap') || derivables.ap
  };

  applicative(type, newDefinition);
}

monad.map = applicative.map;
monad.ap = applicative.ap;
monad.pure = applicative.pure;
module.exports = monad;

monad(Array, {
  chain: function(f) {
    return this.map(function(x) { return f(x); })
        .reduce(function(list, x) { return list.concat(x); }, []);
  }
});

Fix derived map to use .constructor.of


define([
], function() {
  "use strict";

  return {
    props: {
      title: {
        type: String,
        default: "Confirm"
      },
      closeCallback: {
        type: Function,
        default: function() {}
      },
      okCallback: {
        type: Function,
        default: function() {}
      }
   },
    template: '<transition name="modal">' +
    '
' +
    '
' +
    '
' +
    '
<slot name="header">
{{ title }}
</slot>
' +
    '
<slot></slot>
' +
    '
' +
    '          <button type="button" class="btn btn-default" @click="closeCallback">Cancel</button>' +
    '          <button class="btn btn-primary primary" @click="okCallback">Ok</button>' +
    '
' +
    '
' +
    '
' +
    '
' +
    '</transition>'
  };
});

define([
], function() {
  "use strict";

  return {
    props: {
      title: {
        type: String,
        default: "Confirm"
      },
      closeCallback: {
        type: Function,
        default: undefined
      },
      okCallback: {
        type: Function,
        default: function() {}
      }
   },
    template: '<transition name="modal">' +
    '
' +
    '
' +
    '
' +
    '
<slot name="header">
{{ title }}
</slot>
' +
    '
<slot></slot>
' +
    '
' +
    '          <button v-if="closeCallback !== undefined" type="button" class="btn btn-default" @click="closeCallback">Cancel</button>' +
    '          <button class="btn btn-primary primary" @click="okCallback">Ok</button>' +
    '
' +
    '
' +
    '
' +
    '
' +
    '</transition>'
  };
});

Change confirm dialog so that it doesn't show cancel button if not callback


'use strict'

var env = process.env.NODE_ENV || 'development'

if (env === 'development') require('dotenv').config()

var conf = module.exports = {
  env: env,
  server: {
    port: process.env.PORT || 3001
  },
  pg: {
    database: process.env.PGDATABASE || 'opbeans'
  },
  redis: process.env.REDIS_URL || null,
  apm: {
    active: env === 'production'
  }
}

switch (env) {
  case 'development':
    conf.server.url = 'http://localhost:' + conf.server.port
    break
  case 'production':
    conf.server.url = 'https://opbeans.com'
    break
  default:
    throw new Error('Unknown environment: ' + env)
}

'use strict'

var env = process.env.NODE_ENV || 'development'

if (env === 'development') require('dotenv').config()

var conf = module.exports = {
  env: env,
  server: {
    port: process.env.PORT || 3001
  },
  pg: {
    database: process.env.PGDATABASE || 'opbeans'
  },
  redis: process.env.REDIS_URL || null,
  apm: {
    active: env === 'production'
  }
}

switch (env) {
  case 'development':
    conf.server.url = 'http://localhost:' + conf.server.port
    break
  case 'production':
    conf.server.url = 'http://www.opbeans.com'
    break
  default:
    throw new Error('Unknown environment: ' + env)
}

Fix production domain name again


/**
 * Main application routes
 */

'use strict';

var express = require('express');
var config = require('./config/environment');
import errors from './components/errors';
import path from 'path';

export default function(app) {

  // Insert routes below
  app.use('/api/achievements', require('./api/achievement'));
  app.use('/api/posts', require('./api/post'));
  app.use('/api/projects', require('./api/project'));
  app.use('/api/commits', require('./api/commit'));
  app.use('/api/users', require('./api/user'));
  app.use('/api/classyear', require('./api/classyear'));
  app.use('/api/smallgroup', require('./api/smallgroup'));
  app.use('/api/attendance', require('./api/attendance'));
  app.use('/api/static', require('./api/static'));

  app.use('/uploads', express.static(config.imageUploadPath));

  app.use('/auth', require('./auth'));

  // All undefined asset or api routes should return a 404
  app.route('/:url(api|auth|components|app|bower_components|assets|uploads|static)/*')
   .get(errors[404]);

  // All other routes should redirect to the index.html
  app.route('/*')
    .get((req, res) => {
      res.sendFile(path.resolve(app.get('appPath') + '/index.html'));
    });
}

/**
 * Main application routes
 */

'use strict';

var express = require('express');
var config = require('./config/environment');
import errors from './components/errors';
import path from 'path';

export default function(app) {

  // Insert routes below
  app.use('/api/achievements', require('./api/achievement'));
  app.use('/api/posts', require('./api/post'));
  app.use('/api/projects', require('./api/project'));
  app.use('/api/commits', require('./api/commit'));
  app.use('/api/users', require('./api/user'));
  app.use('/api/classyear', require('./api/classyear'));
  app.use('/api/smallgroup', require('./api/smallgroup'));
  app.use('/api/attendance', require('./api/attendance'));
  app.use('/api/static', require('./api/static'));

  app.use('/uploads', express.static(config.imageUploadPath));

  app.use('/auth', require('./auth'));

  // All undefined asset or api routes should return a 404
  app.route('/:url(api|auth|components|app|bower_components|assets|uploads)/*')
   .get(errors[404]);

  // All other routes should redirect to the index.html
  app.route('/*')
    .get((req, res) => {
      res.sendFile(path.resolve(app.get('appPath') + '/index.html'));
    });
}

Revert changes for adding "static" to route


// Load environment variables
if (process.env.NODE_ENV === 'development') {
  require('dotenv').config({ path: './env/development.env' });
}

var express = require('express');
var passport = require('passport');
var util = require('./lib/utility.js');

var app = express();

// Initial Configuration, Static Assets, & View Engine Configuration
require('./config/initialize.js')(app, express);
// Authentication Middleware: Express Sessions, Passport Strategy
require('./config/auth.js')(app, express, passport);

// Pre-Authentication Routes & OAuth Requests
require('./routes/auth-routes.js')(app, passport);

//Authentication check currently commented out, uncomment line to re-activate
// app.use(util.ensureAuthenticated);

// View Routes
require('./routes/view-routes.js')(app);
// API Routes
require('./routes/api-routes.js')(app);

// Wildcard route
app.get('/*', function(req, res) {
  res.redirect('/');
})

app.listen(Number(process.env.PORT), process.env.HOST, function() {
  console.log('NODE_ENV: ' + process.env.NODE_ENV);
  console.log(process.env.APP_NAME + ' is listening at ' + process.env.HOST + ' on port ' + process.env.PORT + '.')
});

// Load environment variables
if (process.env.NODE_ENV === 'development') {
  require('dotenv').config({ path: './env/development.env' });
}

var express = require('express');
var passport = require('passport');
var util = require('./lib/utility.js');

var app = express();

// Initial Configuration, Static Assets, & View Engine Configuration
require('./config/initialize.js')(app, express);
// Authentication Middleware: Express Sessions, Passport Strategy
require('./config/auth.js')(app, express, passport);

// Pre-Authentication Routes & OAuth Requests
require('./routes/auth-routes.js')(app, passport);

//Authentication check currently commented out, uncomment line to re-activate
app.use(util.ensureAuthenticated);

// View Routes
require('./routes/view-routes.js')(app);
// API Routes
require('./routes/api-routes.js')(app);

// Wildcard route
app.get('/*', function(req, res) {
  res.redirect('/');
})

app.listen(Number(process.env.PORT), process.env.HOST, function() {
  console.log('NODE_ENV: ' + process.env.NODE_ENV);
  console.log(process.env.APP_NAME + ' is listening at ' + process.env.HOST + ' on port ' + process.env.PORT + '.')
});

Adjust auth line to keep specs passing


var
  express = require( 'express' ),
  mongoose = require( 'mongoose' ),
  reqExtend = require( 'request-extend' ),
  config = require( './config' ),
  app = express();

//var
//  db = mongoose.connect( config.db.URL ),
//  models = require( './models' )({ mongoose: mongoose, db: db });

app
  .use( express.bodyParser() )
//  .use( reqExtend( 'models', models ))
  .use( reqExtend( 'config', config ))
  .use( express.static( __dirname + '/../client/public/' ))
  .use( app.router );

app.set( 'views', __dirname + '../client/public/' );
app.engine( 'html', require('ejs').renderFile );

require( './router' )( app );

app.listen( config.port );

console.log( 'WAPM app listening on port ' + config.port );

module.exports = app;

var
  express = require( 'express' ),
  mongoose = require( 'mongoose' ),
  reqExtend = require( 'request-extend' ),
  config = require( './config' ),
  app = express();

app
  .use( express.bodyParser() )
  .use( reqExtend( 'config', config ))
  .use( express.static( __dirname + '/../client/public/' ))
  .use( app.router );

app.set( 'views', __dirname + '../client/public/' );
app.engine( 'html', require('ejs').renderFile );

require( './router' )( app );

app.listen( config.port );

console.log( 'WAPM app listening on port ' + config.port );

module.exports = app;

Remove commented out old database hooks


var path = require('path');
var fs = require('../../utils/fs');

/**
    Resolve path to cover file to use

    @param {Output}
    @return {String}
*/
function getCoverPath(output) {
    var outputRoot = output.getRoot();
    var book = output.getBook();
    var config = book.getConfig();
    var cover = config.getValue('cover', 'cover.jpg');

    // Resolve to absolute
    cover = fs.pickFile(outputRoot, cover);
    if (cover) {
        return cover;
    }

    // Multilingual? try parent folder
    if (book.isLanguageBook()) {
        cover = fs.pickFile(path.join(outputRoot, '..'), cover);
    }

    return cover;
}

module.exports = getCoverPath;

var path = require('path');
var fs = require('../../utils/fs');

/**
    Resolve path to cover file to use

    @param {Output}
    @return {String}
*/
function getCoverPath(output) {
    var outputRoot = output.getRoot();
    var book = output.getBook();
    var config = book.getConfig();
    var coverName = config.getValue('cover', 'cover.jpg');

    // Resolve to absolute
    var cover = fs.pickFile(outputRoot, coverName);
    if (cover) {
        return cover;
    }

    // Multilingual? try parent folder
    if (book.isLanguageBook()) {
        cover = fs.pickFile(path.join(outputRoot, '..'), coverName);
    }

    return cover;
}

module.exports = getCoverPath;

Fix get of cover for multilingual books


//@flow

import styled from "styled-components";

export const Svg = styled.svg.attrs({
  viewBox: "0 0 24 24"
})`
  ${({ theme, isActive, stateful }: { theme: Theme, isActive: boolean, stateful: boolean }): string => `

    position: relative;
    height: ${theme.scale.s1(2)};
    width: ${theme.scale.s1(2)};
    ${theme.utils.baseAdjust(6)}
    padding-left: ${theme.scale.s8(-2)};
    transform-origin: 60% 60%;
    will-change: transform fill;
    transition: all 0.2s ease-in-out;
    ${isActive && stateful ? `
      fill: ${theme.effect.darken(0.2, theme.color.black)};
      transform: rotate(180deg);

    ` : ``}

  `}
`;

//@flow

import styled from "styled-components";

export const Svg = styled.svg.attrs({
  className: "chevron__svg",
  viewBox: "0 0 24 24"
})`
  ${({
    theme,
    isActive,
    stateful
  }: {
    theme: Theme,
    isActive: boolean,
    stateful: boolean
  }): string => `

    position: relative;
    height: ${theme.scale.s1(2)};
    width: ${theme.scale.s1(2)};
    top: ${theme.scale.s1(-9)};
    padding-left: ${theme.scale.s8(-2)};
    transform-origin: 60% 60%;
    will-change: transform fill;
    transition: all 0.2s ease-in-out;
    ${isActive && stateful
      ? `
      fill: ${theme.effect.darken(0.2, theme.color.black)};
      transform: rotate(180deg);

    `
      : ``}

  `}
`;

Add top positioning to chevron and reformat with Prettify


var nc_debug;

angular.module('gitphaser')
  .controller('NearbyCtrl', NearbyCtrl);

// @controller NearbyCtrl
// @params: $scope, $reactive
// @route: /tab/nearby
//
// Exposes Meteor mongo 'connections' to DOM, filtered against current user as 'transmitter'
// Subscription to 'connections' is handled in the route resolve. Also
// exposes GeoLocate service (for the maps view) and Notify service (to trigger notification when user
// clicks on list item to see profile)
function NearbyCtrl ($scope, $reactive, Notify, GeoLocate ){
  $reactive(this).attach($scope);

  var self = this;

  // Slide constants bound to the GeoLocate directive
  // and other DOM events, trigger updates based on
  // whether we are looking at List || Map view.
  self.listSlide = 0
  self.mapSlide = 1;
  self.slide = 0;

  // Services
  self.geolocate = GeoLocate;
  self.notify = Notify;

  self.helpers({
      connections: function () {
        if (Meteor.userId()){
          return Connections.find( {transmitter: Meteor.userId() } );
        }
      }
  });

};

Test push post repo transfer to git-phaser org


'use strict';

/* global Connector */

Connector.playerSelector = '#player-controls';

Connector.artistSelector = '.track.playing .info .artist-name';

Connector.trackSelector = '.track.playing .info .track-name';

Connector.trackArtImageSelector = '.playing .track-image img';

Connector.playButtonSelector = '.toggle-play';

Connector.isPlaying = function () {
	return $('.toggle-play').hasClass('icon-pause');
};

'use strict';

/* global Connector */

Connector.playerSelector = '#player-controls';

Connector.artistSelector = '.current-track .info .artist-name';

Connector.trackSelector = '.current-track .info .track-name';

Connector.trackArtImageSelector = '.current-track img';

Connector.playButtonSelector = '#player-controls .icon-play';

Connector.durationSelector = '.track-length';

Connector.currentTimeSelector = '.elapsed-time';

Change selectors according to @Paszt comments


/* jshint node:true */

var options = {
  "framework": "qunit",
  "test_page": "tests/index.html?hidepassed",
  "disable_watching": true,
  "launch_in_ci": [
    "Chrome",
    "Firefox",
  ],
  "launch_in_dev": [
    "Chrome",
    "Firefox",
    "Safari",
  ],
  browser_args: {
    Chrome: {
      mode: 'ci',
      args: [
        '--disable-gpu',
        '--headless',
        '--remote-debugging-port=0',
        '--window-size=1440,900'
      ]
    },
    Firefox: {
      mode: 'ci',
      args: [
        '--headless',
        '--window-size=1440,900'
      ]
    },
  }
};

module.exports = options;

/* jshint node:true */

var options = {
  "framework": "qunit",
  "test_page": "tests/index.html?hidepassed",
  "disable_watching": true,
  "launch_in_ci": [
    "Chrome",
    "Firefox",
  ],
  "launch_in_dev": [
    "Chrome",
    "Firefox",
    "Safari",
  ],
  browser_args: {
    Chrome: {
      mode: 'ci',
      args: [
        '--disable-gpu',
        '--headless',
        '--no-sandbox',
        '--remote-debugging-port=0',
        '--window-size=1440,900'
      ]
    },
    Firefox: {
      mode: 'ci',
      args: [
        '--headless',
        '--window-size=1440,900'
      ]
    },
  }
};

module.exports = options;

Add `--no-sandbox` to Chrome args in CI.


import Em from 'ember';
import Row from 'llama-table/controllers/row';
import { makeArray } from 'llama-table/computed';
var computed = Em.computed;
var map = computed.map;
var sort = computed.sort;
var reads = computed.reads;

var SortedRowsMixin = Em.Mixin.create({
	_rowsSource: makeArray('rows'),

	_rowsSortOrder: makeArray('sortProperties'),

	_rowsMapped: map('_rowsSource', function (model) {
		var Controller = this.get('itemController') || Row;
		if (Controller) {
			return Controller.create({ model });
		}
		return model;
	}),

	_rowsSorted: sort('_rowsMapped', '_rowsSortOrder'),

	/**
	 * Row values array with added sorting functionality. Uses a custom
	 *   'RowsController' if table has subcontent. Does not construct this
	 *   custom controller if it is not necessary.
	 * @property {Ember.ArrayProxy} sortedRows
	 */
	sortedRows: reads('_rowsSorted'),
});

export default SortedRowsMixin;

import Em from 'ember';
import Row from 'llama-table/controllers/row';
import { makeArray } from 'llama-table/computed';
var computed = Em.computed;
var map = computed.map;
var sort = computed.sort;
var reads = computed.reads;

var SortedRowsMixin = Em.Mixin.create({
	_rowsSource: makeArray('rows'),

	_rowsSortOrder: makeArray('sortProperties'),

	_rowsMapped: map('_rowsSource', function (model) {
		if (!(model instanceof Row)) {
			return Row.create({ model });
		}

		return model;
	}),

	_rowsSorted: sort('_rowsMapped', '_rowsSortOrder'),

	/**
	 * Row values array with added sorting functionality. Uses a custom
	 *   'RowsController' if table has subcontent. Does not construct this
	 *   custom controller if it is not necessary.
	 * @property {Ember.ArrayProxy} sortedRows
	 */
	sortedRows: reads('_rowsSorted'),
});

export default SortedRowsMixin;

Remove itemControllers as they are deprecated


const DRAW_SIZE = 32;

function newContext() {
  const canvas = document.createElement('canvas');
  canvas.width = canvas.height = DRAW_SIZE * 2;
  return canvas.getContext('2d');
}

export function prepareCanvasContext(context) {
  if (!context) {
    context = newContext();
    context.fillStyle = "#000";
    context.font = `${DRAW_SIZE}px "Apple Color Emoji","Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Arial`;
  } else {
    context.clearRect(0, 0, DRAW_SIZE * 2, DRAW_SIZE * 2);
  }

  return context;
}

export function canDrawCharacter(character, context) {
  context = prepareCanvasContext(context);
  context.fillText(character, 0, DRAW_SIZE);

  return context.getImageData(DRAW_SIZE / 2, DRAW_SIZE / 2, 1, 1).data[0] !== 0;
}

export function getCharacterWidth(character, context) {
  context = prepareCanvasContext(context);

  return context.measureText(character).width;
}

const DRAW_SIZE = 32;

function newContext() {
  const canvas = document.createElement('canvas');
  canvas.width = canvas.height = DRAW_SIZE * 2;
  return canvas.getContext('2d');
}

export function prepareCanvasContext(context) {
  if (!context) {
    context = newContext();
    context.fillStyle = "#000";
    context.font = `${DRAW_SIZE}px "Apple Color Emoji","Segoe UI","Segoe UI Emoji","Segoe UI Symbol",Arial`;
  } else {
    context.clearRect(0, 0, DRAW_SIZE * 2, DRAW_SIZE * 2);
  }

  return context;
}

export function canDrawCharacter(character, context) {
  context = prepareCanvasContext(context);
  context.fillText(character, 0, DRAW_SIZE);

  return context.getImageData(DRAW_SIZE / 2 + 2, DRAW_SIZE / 2, 1, 1).data[0] !== 0;
}

export function getCharacterWidth(character, context) {
  context = prepareCanvasContext(context);

  return context.measureText(character).width;
}

Fix detection on Windows 10 Anniversary


const itemsPerPage = 100;
export const GITHUB_URL = `https://api.github.com/search/code?per_page=${itemsPerPage}&q=repo%3Atddbin%2Fkatas+language%3AJavaScript+path%3Akatas%2Fes6%2Flanguage`;

const itemsPerPage = 100;
const searchQuery = encodeURIComponent('repo:tddbin/katas+language:JavaScript+path:katas/es6/language');
export const GITHUB_URL = `https://api.github.com/search/code?per_page=${itemsPerPage}&q=${searchQuery}`;

Clean up this looong constant.


var Events = {

  scrollTimer: null,
  stopTimer: null,

  scroll: function (ev, me) {
    var cache = me.cache,
        now = getTime();

    if(me.disableScrollEv) { return; }

    if (!G.pauseCheck) {
      me.fireCustomEvent('scrollstart');
    }
    G.pauseCheck = true;

    if( !cache.now || now > cache.now + GS.scrollMinUpdateInterval ) {
      cache.now = now;

      clearTimeout(me.timerScroll);
      me.timerScroll = setTimeout(function () {
        _invoke(me.scrollbars, 'update');
      }, GS.scrollMinUpdateInterval);

      clearTimeout(me.timerStop);
      me.timerStop = setTimeout(function () {
        Events.scrollStop(me);
      }, me.settings.scrollStopDelay);
    }
  },

  touchstart: function (ev, me) {
    G.pauseCheck = false;
    if(me.settings.fixTouchPageBounce) {
      _invoke(me.scrollbars, 'update', [true]);
    }
  },

  touchend: function (ev, me) {
    // prevents touchmove generate scroll event to call
    // scrollstop  while the page is still momentum scrolling
    clearTimeout(me.timerStop);
  },

  scrollStop: function (me) {
    // update position, cache and detect edge
    // _invoke(me.scrollbars, 'update');

    // fire custom event
    me.fireCustomEvent('scrollstop');

    // restore check loop
    G.pauseCheck = false;
  }

};

var Events = {

  scrollTimer: null,
  stopTimer: null,

  scroll: function (ev, me) {
    var cache = me.cache,
        now = getTime();

    if(me.disableScrollEv) { return; }

    if (!G.pauseCheck) {
      me.fireCustomEvent('scrollstart');
    }
    G.pauseCheck = true;

    if( !cache.now || now > cache.now + GS.scrollMinUpdateInterval ) {
      cache.now = now;

      clearTimeout(cache.timerScroll);
      cache.timerScroll = setTimeout(function () {
        _invoke(me.scrollbars, 'update');
      }, GS.scrollMinUpdateInterval);

      clearTimeout(cache.timerStop);
      cache.timerStop = setTimeout(function () {
        Events.scrollStop(me);
      }, me.settings.scrollStopDelay);
    }
  },

  touchstart: function (ev, me) {
    G.pauseCheck = false;
    if(me.settings.fixTouchPageBounce) {
      _invoke(me.scrollbars, 'update', [true]);
    }
  },

  touchend: function (ev, me) {
    // prevents touchmove generate scroll event to call
    // scrollstop  while the page is still momentum scrolling
    clearTimeout(me.cache.timerStop);
  },

  scrollStop: function (me) {
    // update position, cache and detect edge
    // _invoke(me.scrollbars, 'update');

    // fire custom event
    me.fireCustomEvent('scrollstop');

    // restore check loop
    G.pauseCheck = false;
  }

};

Save timer instances to internal cache obj


import * as PIXI from 'pixi.js';
import * as store from './store';
import * as view from './view';

export const app = new PIXI.Application({antialias: true, transparent: true});
document.getElementById('mimaviz').appendChild(app.view);

export const rendererSize = {width: app.renderer.width, height: app.renderer.height};

app.stage.addChild(store.canvasView);

store.render();
store.store.subscribe(store.render);

/*
 MIMAviz - A modern browser friendly MIMA visualization

 MIMA (Minimalmachine) is a simple processor model based on von Neumann architecture, used for
 educational purposes at the KIT. It is developed by Prof. Tamim Asfour.

 This is a rewrite project of the MIMA simulation (http://ti.ira.uka.de/Visualisierungen/Mima)
 in Javascript and friends, created by Xiaoru Li and distributed under MIT license (see LICENSE).

 The German descriptions in this visualization were largely borrowed from the original MIMA
 simulation, created by Thorsten Rapp and supervised by Prof. Tamim Asfour.
 */

import * as PIXI from 'pixi.js';
import * as store from './store';

export const app = new PIXI.Application({antialias: true, transparent: true});
document.getElementById('mimaviz').appendChild(app.view);

export const rendererSize = {width: app.renderer.width, height: app.renderer.height};

app.stage.addChild(store.canvasView);

store.render();
store.store.subscribe(store.render);

Add mention of TI Website to source code


import express from 'express';
import LEX from 'letsencrypt-express';

import configureHelmet from './security/configure-helmet';
import database from './database';
import log from './log';
import requestLogger from './log/request-logger';
import userRoutes from './routes/users';
import postRoutes from './routes/posts';
import notFoundRoute from './routes/not-found';

database.sync()
  .then(() => {
    const app = express();
    configureHelmet(app);
    app.use(requestLogger);

    app.use('/v2.0/users', userRoutes);
    app.use('/v2.0/posts', postRoutes);
    app.use(notFoundRoute);

    const port = process.env.PORT;

    const lex = LEX.create({
      approveRegistration: (hostname, callback) => {
        callback(null, {
          domains: [hostname],
          email: process.env.CSBLOGS_LETS_ENCRYPT_EMAIL_ADDRESS,
          agreeTos: true
        });
      }
    });

    lex.onRequest = app;
    lex.listen([], [port], function onListen() {
      const protocol = ('requestCert' in this) ? 'https' : 'http';
      const address = this.address();
      log.info({
        address: `${protocol}://${address.address === '::' ? 'localhost' : address.address}:${address.port}`
      }, 'CSBlogs API Server now running');
    });
  });

import express from 'express';
import LEX from 'letsencrypt-express';

import configureHelmet from './security/configure-helmet';
import database from './database';
import log from './log';
import requestLogger from './log/request-logger';
import userRoutes from './routes/users';
import postRoutes from './routes/posts';
import notFoundRoute from './routes/not-found';

database.sync()
  .then(() => {
    const app = express();
    configureHelmet(app);
    app.use(requestLogger);

    app.use('/v2.0/users', userRoutes);
    app.use('/v2.0/posts', postRoutes);
    app.use(notFoundRoute);

    const lex = LEX.create({
      approveRegistration: (hostname, callback) => {
        callback(null, {
          domains: [hostname],
          email: process.env.CSBLOGS_LETS_ENCRYPT_EMAIL_ADDRESS,
          agreeTos: true
        });
      }
    });

    const port = process.env.PORT;

    lex.onRequest = app;
    lex.listen([], [port], function onListen() {
      const protocol = ('requestCert' in this) ? 'https' : 'http';
      const address = this.address();
      log.info({
        address: `${protocol}://${address.address === '::' ? 'localhost' : address.address}:${address.port}`
      }, 'CSBlogs API Server now running');
    });
  });

Reduce variable lifespan of port