import http from 'http';
import express from 'express';
import bodyParser from 'body-parser';
import cors from 'cors';
import { makeExecutableSchema } from 'graphql-tools';
import { graphqlExpress } from 'apollo-server-express';
import graphqlPlayground from 'graphql-playground-middleware-express';
import checkEnv from 'check-env';
import { graphqlSchema, graphqlResolvers } from './graphql';
import config from './constants/config';

checkEnv(['encryption_key']);

const app = express();
app.server = http.createServer(app);

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cors());

const executableSchema = makeExecutableSchema({
  typeDefs: [graphqlSchema],
  resolvers: graphqlResolvers,
});

app.use(
  '/graphql',
  bodyParser.json(),
  graphqlExpress({
    schema: executableSchema,
    formatError: error => ({
      message: 'Internal Server Error',
      path: error.path,
    }),
    tracing: true,
  }),
);

app.get('/playground', graphqlPlayground({ endpoint: '/graphql' }));

app.get('/', (req, res) => res.redirect('/playground'));

app.server.listen(process.env.PORT || config.server.port);
// eslint-disable-next-line no-console
console.log(`🚀  Server listening on port ${app.server.address().port}...`);

import http from 'http';
import express from 'express';
import bodyParser from 'body-parser';
import cors from 'cors';
import { makeExecutableSchema } from 'graphql-tools';
import { graphqlExpress } from 'apollo-server-express';
import graphqlPlayground from 'graphql-playground-middleware-express';
import checkEnv from 'check-env';
import { graphqlSchema, graphqlResolvers } from './graphql';
import config from './constants/config';

checkEnv(['encryption_key']);

const PORT = process.env.PORT || config.server.port;

const app = express();
app.server = http.createServer(app);

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cors());

const executableSchema = makeExecutableSchema({
  typeDefs: [graphqlSchema],
  resolvers: graphqlResolvers,
});

app.use(
  '/graphql',
  bodyParser.json(),
  graphqlExpress({
    schema: executableSchema,
    formatError: error => ({
      message: 'Internal Server Error',
      path: error.path,
    }),
    tracing: true,
  }),
);

app.get('/playground', graphqlPlayground({ endpoint: '/graphql' }));

app.get('/', (req, res) => res.redirect('/playground'));

app.server.listen(PORT);
// eslint-disable-next-line no-console
console.log(`🚀  Server listening on port ${PORT}...`);

Fix `port of undefined` error


module.exports = function (grunt) {
  var sourceFiles = ['Gruntfile.js', 'lib/*.js', '*.js'];

  grunt.loadNpmTasks('grunt-mocha-test');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-jsbeautifier');

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    mochaTest: {
      options: {
        reporter: 'spec',
        require: ['should']
      },
      src: ['test/*.js']
    },
    jshint: {
      files: sourceFiles,
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        latedef: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        boss: true,
        eqnull: true,
        node: true
      }
    },
    jsbeautifier: {
      options: {
        js: {
          indentSize: 2,
          jslintHappy: true
        }
      },
      files: sourceFiles
    }
  });

  grunt.registerTask('test', ['mochaTest']);
  grunt.registerTask('lint', ['jshint']);
  grunt.registerTask('beautify', ['jsbeautifier']);
};

module.exports = function (grunt) {
  var sourceFiles = ['Gruntfile.js', 'lib/*.js', '*.js'];

  grunt.loadNpmTasks('grunt-mocha-test');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-jsbeautifier');

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    mochaTest: {
      options: {
        reporter: 'spec',
        require: ['should']
      },
      src: ['test/*.js']
    },
    jshint: {
      files: sourceFiles,
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        latedef: true,
        noarg: true,
        sub: true,
        undef: true,
        boss: true,
        eqnull: true,
        node: true
      }
    },
    jsbeautifier: {
      options: {
        js: {
          indentSize: 2,
          jslintHappy: true
        }
      },
      files: sourceFiles
    }
  });

  grunt.registerTask('test', ['mochaTest']);
  grunt.registerTask('lint', ['jshint']);
  grunt.registerTask('beautify', ['jsbeautifier']);
};

Stop Q from triggering lint errors


import { expect } from 'chai';

import Sheet from 'Src/sheet';

import sheet1x1 from 'Test/fixtures/sheet-1x1';

describe('Sheet', () => {
  let sheet;

  it('should have data property', () => {
    sheet = new Sheet(sheet1x1);
    expect(sheet).to.have.property('data');
  });

  it('should have name property', () => {
    sheet = new Sheet(sheet1x1);
    expect(sheet).to.have.property('name');
  });

  it('should set data property on initialization', () => {
    sheet = new Sheet(sheet1x1);
    expect(sheet.data).to.equal(sheet1x1);
  });

  it('should throw an Error if data property was not given to constructor', () => {
    expect(() => new Sheet()).to.throw(Error);
  });
});

import { expect } from 'chai';

import Sheet from 'Src/sheet';

import sheet1x1 from 'Test/fixtures/sheet-1x1';

describe('Sheet', () => {
  let sheet;

  it('should have data property', () => {
    sheet = new Sheet(sheet1x1);
    expect(sheet).to.have.property('data');
  });

  it('should have name property', () => {
    sheet = new Sheet(sheet1x1);
    expect(sheet).to.have.property('name');
  });

  it('should set data property on initialization', () => {
    sheet = new Sheet(sheet1x1);
    expect(sheet.data).to.equal(sheet1x1);
  });

  it('should set name property on initialization', () => {
    const name = 'defaultName';
    sheet = new Sheet(sheet1x1, name);
    expect(sheet.name).to.equal(name);
  });

  it('should throw an Error if data property was not given to constructor', () => {
    expect(() => new Sheet()).to.throw(Error);
  });
});

Add name initialization test case


module.exports = function(Weatherreport) {
	Weatherreport.handleChangeError = function(err) {
		console.warn("Cannot update change records for WeatherReport: ", err);
	};
};

module.exports = function(Weatherreport) {
	Weatherreport.handleChangeError = function(err) {
		console.warn("Cannot update change records for WeatherReport: ", err);
	};

	Weatherreport.withPositions = function(groupId, startDate, endDate, cb) {
		Weatherreport.find({
			include: [{
				relation: 'Position',
				scope: {
					where: {
						timestamp: {
							gte: new Date(startDate),
							lte: new Date(endDate)
						}
					}
				}
			},
			{
				relation: 'MobileUser',
				scope: {
					where: {
						groupId: groupId
					}
				}
			}]
		}, function(err, results) {
			if (err) return cb(err);
			var filteredResults = results.filter(function (result) {
				return result.Position() && result.MobileUser();
			});
			cb(null, filteredResults);
		});
	};

	Weatherreport.remoteMethod('withPositions', {
		http: {path: '/with-positions', verb: 'get'},
		accepts: [
			{arg: 'groupId', type: 'string', 'http': {source: 'query'}, required: true},
			{arg: 'startdate', type: 'string', 'http': {source: 'query'}, required: true},
			{arg: 'enddate', type: 'string', 'http': {source: 'query'}, required: true}
		],
		returns: {arg: 'WeatherReports', type: 'string'}
	});
};

Add with-position WeatherReport endpoint that matches groupId through MobileUser relation.


(function() {
    'use strict';

    angular
        .module('sentryApp')
        .config(stateConfig);

    stateConfig.$inject = ['$stateProvider'];

    function stateConfig($stateProvider) {
        $stateProvider.state('password', {
            parent: 'account',
            url: '/password',
            data: {
                authorities: ['ROLE_USER'],
                pageTitle: 'Password'
            },
            views: {
                'content@': {
                    templateUrl: 'app/account/password/password.html',
                    controller: 'PasswordController',
                    controllerAs: 'vm'
                }
            }
        });
    }
})();

(function() {
    'use strict';

    angular
        .module('sentryApp')
        .config(stateConfig);

    stateConfig.$inject = ['$stateProvider'];

    function stateConfig($stateProvider) {
        $stateProvider.state('password', {
            parent: 'account',
            url: '/password',
            data: {
                authorities: ['ROLE_ADMIN'],
                pageTitle: 'Password'
            },
            views: {
                'content@': {
                    templateUrl: 'app/account/password/password.html',
                    controller: 'PasswordController',
                    controllerAs: 'vm'
                }
            }
        });
    }
})();

Disable password change on the client


var del = require('del');
var _ = require('lodash');

function clean(target, done) {
	var dir = './' + target;
	var deleteList = [dir + '/*'];
	deleteList = deleteList.concat(getPreservedFiles(dir));
	return del(deleteList, done);
}

var preservedFiles = [
	'web.config',
	'bower.json',
];

function getPreservedFiles(directory) {
	return _.map(preservedFiles, function(file) {
		return '!' + directory + '/' + file;
	});
}

module.exports = clean;

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

module.exports.config = function(gulp) {
	gulp.task('clean', ['clean.debug']);

	gulp.task('clean.debug', function (done) {
		return clean(defaults.debugFolder, done);
	});

	gulp.task('clean.release', function (done) {
		return clean(defaults.releaseFolder, done);
	});
};

var del = require('del');
var _ = require('lodash');

function clean(target, done) {
	var dir = './' + target;
	var deleteList = [dir + '/*'];
	deleteList = deleteList.concat(getPreservedFiles(dir));
	return del(deleteList, done);
}

var preservedFiles = [
	'web.config',
];

function getPreservedFiles(directory) {
	return _.map(preservedFiles, function(file) {
		return '!' + directory + '/' + file;
	});
}

module.exports = clean;

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

module.exports.config = function(gulp) {
	gulp.task('clean', ['clean.debug']);

	gulp.task('clean.debug', function (done) {
		return clean(defaults.debugFolder, done);
	});

	gulp.task('clean.release', function (done) {
		return clean(defaults.releaseFolder, done);
	});
};

Clean bower js files now since we will be copying these from the main repo


import Event from './event';

const Day = ({ events }) => {

  const DAY_NAMES = [ 'Mandag', 'Tirsdag', 'Onsdag', 'Torsdag', 'Fredag', 'Lørdag', 'Søndag' ];
  const MONTH_NAMES = [ 'januar', 'februar', 'mars', 'april', 'mai', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'desember' ];

  const DAY = events[ 0 ].start_time;
  const DAY_NAME = DAY_NAMES[ DAY.getDay() ];
  const DATE = DAY.getDate();
  const MONTH_NAME = MONTH_NAMES[ DAY.getMonth() ];

  return (

{`${DAY_NAME} ${DATE}. ${MONTH_NAME}`}

      { events.map((e, id) => {
        return <Event title={e.title} start_time={e.start_time} content={e.content} key={id}/>
      })}

  );
};

export default Day;

import Event from './event';

const DAY_NAMES = [ 'Mandag', 'Tirsdag', 'Onsdag', 'Torsdag', 'Fredag', 'Lørdag', 'Søndag' ];
const MONTH_NAMES = [ 'januar', 'februar', 'mars', 'april', 'mai', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'desember' ];

const Day = ({ events }) => {

  const DAY = events[ 0 ].start_time;
  const DAY_NAME = DAY_NAMES[ DAY.getDay() ];
  const DATE = DAY.getDate();
  const MONTH_NAME = MONTH_NAMES[ DAY.getMonth() ];

  return (

{`${DAY_NAME} ${DATE}. ${MONTH_NAME}`}

      { events.map((e, id) => {
        return <Event title={e.title} start_time={e.start_time} content={e.content} key={id}/>
      })}

  );
};

export default Day;

Move constants outside of component as they didn't really need to be in there


module.exports = function(grunt) {
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    concat: {
      options: {
        separator: ';',
      },
      dist: {
        src: ['js/actions.js', 'js/main.js', 'js/vendor/fuse.min.js'],
        dest: 'js/dist/built.js',
      },
    },
    watch: {
      js: {
        files: [
          'js/*.js'

        ],
        tasks: [
          'default',
        ]
      }
    }
  });
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.registerTask('default', ['concat']);
}

module.exports = function(grunt) {
  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    concat: {
      options: {
        separator: ';',
      },
      dist: {
        src: ['js/actions.js', 'js/main.js', 'js/vendor/fuse.min.js'],
        dest: 'js/dist/built.js',
      },
    },
    watch: {
      js: {
        files: [
          'js/*.js',
          'css/*.css'
        ],
        tasks: [
          'default',
        ]
      }
    }
  });
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.registerTask('default', ['concat']);
}

Add css to grunt watch.


module.exports = function(grunt) {
	grunt.initConfig({
		jshint: {
			options: {
				jshintrc: '.jshintrc'
			},
			files: [
				'Gruntfile.js',
				'package.json',
				'js/**/*.js'
			]
		},
		connect: {
			www: {
				options: {
					base: '.',
					port: 4545
				}
			}
		},
		ghost: {
			dist: {
				filesSrc:  ['tests/integration/casperjs/*_test.js'],
				options: {
					args: {
						baseUrl: 'http://localhost:' +
							'<%= connect.www.options.port %>/'
					},
					direct: false,
					logLevel: 'error',
					printCommand: false,
					printFilePaths: true
				}
			}
		}
	});

	grunt.loadNpmTasks('grunt-contrib-connect');
	grunt.loadNpmTasks('grunt-contrib-jshint');
	grunt.loadNpmTasks('grunt-ghost');

	grunt.registerTask('test', ['jshint', 'connect', 'ghost']);

};

module.exports = function(grunt) {
	grunt.initConfig({
		jshint: {
			options: {
				jshintrc: '.jshintrc'
			},
			files: [
				'Gruntfile.js',
				'package.json',
				'js/*.js'
			]
		},
		connect: {
			www: {
				options: {
					base: '.',
					port: 4545
				}
			}
		},
		ghost: {
			dist: {
				filesSrc:  ['tests/integration/casperjs/*_test.js'],
				options: {
					args: {
						baseUrl: 'http://localhost:' +
							'<%= connect.www.options.port %>/'
					},
					direct: false,
					logLevel: 'error',
					printCommand: false,
					printFilePaths: true
				}
			}
		}
	});

	grunt.loadNpmTasks('grunt-contrib-connect');
	grunt.loadNpmTasks('grunt-contrib-jshint');
	grunt.loadNpmTasks('grunt-ghost');

	grunt.registerTask('test', ['jshint', 'connect', 'ghost']);

};

Set back original jshint path


$(function() {
    $("#menu-toggle").click(function(e) {
        e.preventDefault()
        $("#wrapper").toggleClass("toggled")
    })

    var timer
    $(window).on('mousemove', function() {
        $('.navbar').addClass('show')
        $('.panel-wrapper, .panel-primary').addClass('down')
        try {
            clearTimeout(timer)
        } catch (e) {}
        timer = setTimeout(function() {
            $('.navbar').removeClass('show')
            $('.panel-wrapper, .panel-primary').removeClass('down')
        }, 3000)
    })
})

$(function() {
    // toggle sidebar
    $("#menu-toggle").click(function(e) {
        e.preventDefault()
        $("#wrapper").toggleClass("toggled")
    })

    // navbar hidden-show
    var timer
    $('#nav-wrapper').on('mouseover', function() {
        $('.navbar').addClass('show')
        $('.panel-wrapper, .panel-primary').addClass('down')
        try {
            clearTimeout(timer)
        } catch (e) {}
        timer = setTimeout(function() {
            $('.navbar').removeClass('show')
            $('.panel-wrapper, .panel-primary').removeClass('down')
        }, 2000)
    })
})

Fix navbar anim to mouseover


var gulp = require('gulp');
var istanbul = require('gulp-istanbul');
var mocha = require('gulp-mocha');
var jscs = require('gulp-jscs');
var jshint = require('gulp-jshint');

gulp.task('pre-test', function() {
  return gulp.src('src/*.js')
    .pipe(istanbul())
    .pipe(istanbul.hookRequire());
});

gulp.task('test', ['pre-test'], function() {
  return gulp.src('test/*.js')
    .pipe(mocha({reporter: 'nyan'}))
    .pipe(istanbul.writeReports());
});

gulp.task('jscs', function() {
  return gulp.src([
      'src/*.js',
      'test/*.js',
      'gulpfile.js'
    ])
    .pipe(jscs())
    .pipe(jscs.reporter());
});

gulp.task('jshint', function() {
  return gulp.src([
      'src/*.js',
      'test/*.js',
      'gulpfile.js'
    ])
    .pipe(jshint())
    .pipe(jshint.reporter());
});

gulp.task('lint', ['jshint', 'jscs']);

gulp.task('default', ['lint', 'test']);

var gulp = require('gulp');
var istanbul = require('gulp-istanbul');
var mocha = require('gulp-mocha');
var jscs = require('gulp-jscs');
var jshint = require('gulp-jshint');

gulp.task('pre-test', function() {
  return gulp.src('src/*.js')
    .pipe(istanbul())
    .pipe(istanbul.hookRequire());
});

gulp.task('test', ['pre-test'], function() {
  return gulp.src('test/*.js')
    .pipe(mocha())
    .pipe(istanbul.writeReports());
});

gulp.task('jscs', function() {
  return gulp.src([
      'src/*.js',
      'test/*.js',
      'gulpfile.js'
    ])
    .pipe(jscs())
    .pipe(jscs.reporter());
});

gulp.task('jshint', function() {
  return gulp.src([
      'src/*.js',
      'test/*.js',
      'gulpfile.js'
    ])
    .pipe(jshint())
    .pipe(jshint.reporter());
});

gulp.task('lint', ['jshint', 'jscs']);

gulp.task('default', ['lint', 'test']);

Switch to standard reporter for mocha


/**
 * Author: Jeff Whelpley
 * Date: 1/21/15
 *
 * Testing out batter
 */
var name    = 'lib/batter';
var taste   = require('taste');
var batter  = taste.target(name);

describe('UNIT ' + name, function () {
    describe('getOptions()', function () {
        it('should set defaults', function () {
            var opts = { rootDir: 'foo', targetDir: 'blah', require: 'choo' };
            var expected = {
                rootDir: 'foo',
                targetDir: 'blah',
                require: 'choo',
                unitTestCode: 'test/unit/**/*.js',
                unitTargetCode: 'lib/**/*.js',
                testDir: 'test'
            };
            taste.addCommandLineArgs(expected);

            var actual = batter.getOptions(opts);
            actual.should.deep.equal(expected);
        });
    });

    describe('getPlugins()', function () {
        it('should return batter by default', function () {
            var rootDir = __dirname.replace('/test' + taste.delim + 'unit', '');
            var opts = { rootDir: 'blah' };
            var expected = [
                { rootDir: rootDir },
                { rootDir: 'blah' }
            ];
            var actual = batter.getPlugins(opts);
            actual.should.deep.equal(expected);
        });
    });
});

/**
 * Author: Jeff Whelpley
 * Date: 1/21/15
 *
 * Testing out batter
 */
var name    = 'lib/batter';
var taste   = require('taste');
var batter  = taste.target(name);

describe('UNIT ' + name, function () {
    describe('getOptions()', function () {
        it('should set defaults', function () {
            var opts = { rootDir: 'foo', targetDir: 'blah', require: 'choo' };
            var expected = {
                rootDir: 'foo',
                targetDir: 'blah',
                tasksets: {
                    default: ['lint', 'test']
                },
                require: 'choo',
                unitTestCode: 'test/unit/**/*.js',
                unitTargetCode: 'lib/**/*.js',
                testDir: 'test'
            };
            taste.addCommandLineArgs(expected);

            var actual = batter.getOptions(opts);
            actual.should.deep.equal(expected);
        });
    });

    describe('getPlugins()', function () {
        it('should return batter by default', function () {
            var rootDir = __dirname.replace('/test' + taste.delim + 'unit', '');
            var opts = { rootDir: 'blah' };
            var expected = [
                { rootDir: rootDir },
                { rootDir: 'blah' }
            ];
            var actual = batter.getPlugins(opts);
            actual.should.deep.equal(expected);
        });
    });
});

Fix for broken unit test


module.exports = function (grunt) {
    // Do grunt-related things in here
    grunt.initConfig({
        pkg : grunt.file.readJSON('package.json'),
        meta : {
            project : '<%= pkg.name %>',
            version : '<%= pkg.version %>',
            banner  : '/*! <%= meta.project %> - v<%= meta.version %> - \n' +
            ' * Copyright (c) Hassan Khan <%= grunt.template.today("yyyy") %>\n' +
            ' */'
        },
        jshint : {
            files        : ['emojify.js']
        },
        uglify : {
            options : {
                banner : '<%= meta.banner %>'
            },
            production : {
                files : {
                    'emojify.min.js' : 'emojify.js'
                }
            }
        }
    });

    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-uglify');

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

module.exports = function (grunt) {
    // Do grunt-related things in here
    grunt.initConfig({
        pkg : grunt.file.readJSON('package.json'),
        meta : {
            project : '<%= pkg.name %>',
            version : '<%= pkg.version %>',
            banner  : '/*! <%= meta.project %> - v<%= meta.version %> - \n' +
            ' * Copyright (c) Hassan Khan <%= grunt.template.today("yyyy") %>\n' +
            ' */'
        },
        jshint : {
            files        : ['emojify.js']
        },
        uglify : {
            options : {
                banner : '<%= meta.banner %>'
            },
            production : {
                files : {
                    'emojify.min.js' : 'emojify.js'
                }
            }
        }
    });

    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-uglify');

    grunt.registerTask(
        'default',
        [
            'jshint',
            'uglify'
        ]
    );

    grunt.registerTask('buildCSS', 'Generate CSS for emojis in /images', function() {
        var fs = require('fs'),
            path = require('path'),
            util = require('util'),
            done = this.async(),
            emojiPath = './images/emoji/',
            emojiCSS = fs.createWriteStream('emojify.css', {'flags': 'w'}),
            buildSelector = function(imageName, encodedImage) {
                return util.format('.emjoi-%s {\n  background:\n    url(data:image/png;base64,%s)\n    no-repeat\n    left-center;\n}\n',
                                   imageName, encodedImage);
            };

        fs.readdir(emojiPath, function (err, files) {
            files.map(function(file) {
                fs.readFile(path.join(emojiPath, file), function(err, data){
                    var base64Image = new Buffer(data, 'binary').toString('base64');
                    emojiCSS.write(buildSelector(file.slice(0, -4), base64Image));
                });
            });
        });
    });
};

Implement buildCSS task, builds emoji.css with all images base64 encoded as styles


module.exports = function (grunt) {
  grunt.initConfig({
    uglify: {
      main: {
        files: {
          'ng-stomp.min.js': ['ng-stomp.js']
        }
      }
    },
    jshint: {
      all: ['*.js', '!*.min.js']
    }
  });

  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.registerTask('default', ['jshint', 'uglify']);
};

module.exports = function (grunt) {
  grunt.initConfig({
    uglify: {
      main: {
        options: {
          preserveComments: 'some'
        },
        files: {
          'ng-stomp.min.js': ['ng-stomp.js'],
          'ng-stomp.standalone.min.js': [
            'bower_components/sockjs/sockjs.min.js',
            'bower_components/stomp-websocket/lib/stomp.min.js',
            'bower_components/stompie/stompie-min.js',
            'ng-stomp.js'
          ]
        }
      }
    },
    jshint: {
      all: ['*.js', '!*.min.js']
    }
  });

  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.registerTask('default', ['jshint', 'uglify']);
};

Add task for standalone file (includes dependencies)


'use strict';

var gulp = require('gulp'),
	nodemon = require('gulp-nodemon'),
	uglify = require('gulp-uglify'),
	sass = require('gulp-sass'),
	minifyCSS = require('gulp-minify-css'),
	rename = require('gulp-rename'),
	concat = require('gulp-concat');

function restartTime () {
	function checkTime(i) {
		return (i < 10) ? '0' + i : i;
	}

	var today = new Date(),
		hrs = checkTime(today.getHours()),
		min = checkTime(today.getMinutes()),
		sec = checkTime(today.getMinutes());

	return hrs + ':' + min + ':' + sec;
}

gulp.task('watch', function () {
	nodemon({ script: 'server.js', ext: 'jade js'})
		.on('restart', function () {
			console.log('Server restarted at ' + restartTime + '!');
			});
});

gulp.task('minify', function () {
	gulp.src('./app/css/*.sass')
		.pipe(sass({
			indentedSyntax: true,
			errLogToConsole: true
			}))
		.pipe(minifyCSS())
		.pipe(rename('main.min.css'))
		.pipe(gulp.dest('./public/css'));

	gulp.src(['./app/controllers/clickController.client.js'])
		.pipe(uglify())
		.pipe(rename('site.min.js'))
		.pipe(gulp.dest('./public/scripts'));

});

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

'use strict';

var gulp = require('gulp'),
	nodemon = require('gulp-nodemon'),
	uglify = require('gulp-uglify'),
	sass = require('gulp-sass'),
	minifyCSS = require('gulp-minify-css'),
	rename = require('gulp-rename'),
	concat = require('gulp-concat');

function restartTime () {
	function checkTime(i) {
		return (i < 10) ? '0' + i : i;
	}

	var today = new Date(),
		hrs = checkTime(today.getHours()),
		min = checkTime(today.getMinutes()),
		sec = checkTime(today.getMinutes());

	return hrs + ':' + min + ':' + sec;
}

gulp.task('watch', function () {
	nodemon({ script: 'server.js', ext: 'jade js'})
		.on('restart', function () {
			console.log('Server restarted at ' + restartTime + '!');
			});
});

gulp.task('minify', function () {
	gulp.src('./app/css/*.sass')
		.pipe(sass({
			indentedSyntax: true,
			errLogToConsole: true
			}))
		.pipe(minifyCSS())
		.pipe(rename('main.min.css'))
		.pipe(gulp.dest('./public/css'));

	gulp.src(['./app/controllers/**/*.client.js'])
		.pipe(uglify())
		.pipe(rename('site.min.js'))
		.pipe(gulp.dest('./public/scripts'));

});

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

Use wildcard in Gulp minify task.


var gulp = require('gulp');
var sass = require('gulp-sass');
var autoprefixer = require('gulp-autoprefixer');
var uglify = require('gulp-uglify');
var pump = require('pump');
var cleanCSS = require('gulp-clean-css');
var imagemin = require('gulp-imagemin');

gulp.task('sass', function() {
    return gulp.src('src/sass/*.scss')
        .pipe(sass())
        .pipe(autoprefixer({ browsers: ['last 3 versions'] }))
        .pipe(cleanCSS())
        .pipe(gulp.dest('build/css'));
});

gulp.task('uglify-js', function() {
    pump([
        gulp.src('src/js/*.js'),
        uglify(),
        gulp.dest('build/js')
    ]);
});

gulp.task('html', function() {
	return gulp.src('src/index.html').pipe(gulp.dest('build'));
});

gulp.task('default', function() {
	gulp.watch('src/sass/*.scss', ['sass']);
	gulp.watch('src/js/*.js', ['uglify-js']);
	gulp.watch('src/index.html', ['html']);
	gulp.src('src/img/*')
        .pipe(imagemin())
        .pipe(gulp.dest('build/img'));
});

var gulp = require('gulp');
var sass = require('gulp-sass');
var autoprefixer = require('gulp-autoprefixer');
var uglify = require('gulp-uglify');
var pump = require('pump');
var cleanCSS = require('gulp-clean-css');
var imagemin = require('gulp-imagemin');

gulp.task('sass', function() {
    return gulp.src('src/sass/main.scss')
        .pipe(sass())
        .pipe(autoprefixer({ browsers: ['last 3 versions'] }))
        .pipe(cleanCSS())
        .pipe(gulp.dest('build/css'));
});

gulp.task('uglify-js', function() {
    pump([
        gulp.src('src/js/*.js'),
        uglify(),
        gulp.dest('build/js')
    ]);
});

gulp.task('html', function() {
	return gulp.src('src/index.html').pipe(gulp.dest('build'));
});

gulp.task('default', function() {
	gulp.watch('src/sass/*.scss', ['sass']);
	gulp.watch('src/js/*.js', ['uglify-js']);
	gulp.watch('src/index.html', ['html']);
	gulp.src('src/img/*')
        .pipe(imagemin())
        .pipe(gulp.dest('build/img'));
});

Modify .scss files to compile


import commander from 'commander';
import containerInit from './init';
import fs from 'fs';
import path from 'path';

commander
  .command('serve')
  .alias('s')
  .description('serve ap-npm')
  .option('--config', "config file to use")
  .action(function(config) {
    let container;
    if (fs.existsSync(config)) {
      console.log("using config: " + config + '\n');
      container = containerInit(config);
    }
    else if (typeof config === 'string') {
      if (fs.existsSync(path.join(__dirname, '../', config))) {
        let configLocation = path.join(__dirname, '../', config);
        console.log("using config: " + configLocation + '\n');
        container = containerInit(configLocation);
      }
    }
    else {
      console.log("using default config\n");
      container = containerInit("../config.json");
    }

    let command = container.get('command-serve');
    command.run();
  });

commander.parse(process.argv);

if (!process.argv.slice(2).length) {
  commander.outputHelp();
}

import commander from 'commander';
import containerInit from './init';
import fs from 'fs';
import path from 'path';

commander
  .command('serve')
  .alias('s')
  .description('serve ap-npm')
  .option('-c, --config', "config file to use")
  .action(function(config) {
    let container;

    if (fs.existsSync(config)) {
      console.log("using config: " + config + '\n');
      container = containerInit(config);
    } else {
      console.log("using default config\n");
      let configLocation = path.join(__dirname, '../', 'config.json');
      container = containerInit(configLocation);
    }

    let command = container.get('command-serve');
    command.run();
  });

commander
  .command('set <prop> <value>')
  .description('sets default config property')
  .action(function(property, value) {
    let container = containerInit(path.join(__dirname, '../', 'config.json'));
    let command = container.get('command-set');
    command.run(property, value);
  });

commander
  .command('init')
  .description('init a npm project using ap-npm config')
  .action(function() {
    let container = containerInit(path.join(__dirname, '../', 'config.json'));
    let command = container.get('command-init');
    command.run(process.cwd());
  });

commander.parse(process.argv);

if (!process.argv.slice(2).length) {
  commander.outputHelp();
}

Add set and init command to ap-npm


#!/usr/bin/env node

import path from 'path';
import yargs from 'yargs';

import { downloadSchema, generate } from '.';

yargs
  .command(
    'download-schema <server>',
    'Download a GraphQL schema from a server',
    {
      output: {
        demand: true,
        describe: 'Output path for GraphQL schema file',
        normalize: true
      }
    },
    async argv => {
      const outputPath = path.resolve(argv.output);
      try {
        await downloadSchema(argv.server, outputPath);
      } catch (error) {
        console.error(error);
      }
    }
  )
  .command(
    'generate <input...>',
    'Generate code from a GraphQL schema and query documents',
    {
      schema: {
        demand: true,
        describe: 'Path to GraphQL schema file',
        normalize: true
      },
      output: {
        demand: true,
        describe: 'Output directory for the generated files',
        normalize: true
      }
    },
    argv => {
      try {
        const inputPaths = argv.input.map(input => path.resolve(input));
        const schemaPath = path.resolve(argv.schema);
        const outputPath = path.resolve(argv.output);
        generate(inputPaths, schemaPath, outputPath);
      } catch (error) {
        console.error(error.stack);
      }
    },
  )
  .showHelpOnFail(false)
  .help()
  .strict()
  .argv

#!/usr/bin/env node

import process from 'process';
import path from 'path';
import yargs from 'yargs';

import { downloadSchema, generate } from '.';

// Make sure unhandled errors in async code are propagated correctly
process.on('unhandledRejection', (error) => { throw error });

yargs
  .command(
    'download-schema <server>',
    'Download a GraphQL schema from a server',
    {
      output: {
        demand: true,
        describe: 'Output path for GraphQL schema file',
        normalize: true
      }
    },
    async argv => {
      const outputPath = path.resolve(argv.output);
      await downloadSchema(argv.server, outputPath);
    }
  )
  .command(
    'generate <input...>',
    'Generate code from a GraphQL schema and query documents',
    {
      schema: {
        demand: true,
        describe: 'Path to GraphQL schema file',
        normalize: true
      },
      output: {
        demand: true,
        describe: 'Output directory for the generated files',
        normalize: true
      }
    },
    argv => {
      const inputPaths = argv.input.map(input => path.resolve(input));
      const schemaPath = path.resolve(argv.schema);
      const outputPath = path.resolve(argv.output);
      generate(inputPaths, schemaPath, outputPath);
    },
  )
  .showHelpOnFail(false)
  .help()
  .strict()
  .argv

Make sure errors result in a non-zero exit code


"use strict";
let platform = require('git-node-platform');
let jsGit = require('../.')(platform);
let fsDb = require('git-fs-db')(platform);
let fs = platform.fs;
let run = require('gen-run');

// Create a filesystem backed bare repo
let repo = jsGit(fsDb(fs("test.git")));

let mock = require('./mock.js');

run(function *() {
  yield repo.setBranch("master");
  console.log("Git database Initialized");

  let head;
  console.log(yield* map(mock.commits, function* (files, message) {
    return head = yield repo.saveAs("commit", {
      tree: yield repo.saveAs("tree", yield* map(files, function* (contents) {
        return {
          mode: 33188, // 0100644,
          hash: yield repo.saveAs("blob", contents)
        };
      })),
      parent: head,
      author: mock.author,
      committer: mock.committer,
      message: message
    });
  }));

  yield repo.updateHead(head);
  console.log("Done");

});

function* map(object, onItem) {
  let obj = {};
  for (let key in object) {
    let value = object[key];
    obj[key] = yield* onItem(value, key);
  }
  return obj;
}

"use strict";
let platform = require('git-node-platform');
let jsGit = require('../.')(platform);
let fsDb = require('git-fs-db')(platform);
let fs = platform.fs;
let run = require('gen-run');

// Create a filesystem backed bare repo
let repo = jsGit(fsDb(fs("test.git")));

let mock = require('./mock.js');

run(function *() {
  yield repo.setBranch("master");
  console.log("Git database Initialized");

  let head;
  console.log(yield* map(mock.commits, function* (files, message) {
    return head = yield repo.saveAs("commit", {
      tree: yield repo.saveAs("tree", yield* map(files, function* (contents) {
        return {
          mode: 33188, // 0o100644,
          hash: yield repo.saveAs("blob", contents)
        };
      })),
      parent: head,
      author: mock.author,
      committer: mock.committer,
      message: message
    });
  }));

  yield repo.updateHead(head);
  console.log("Done");

});

function* map(object, onItem) {
  let obj = {};
  for (let key in object) {
    let value = object[key];
    obj[key] = yield* onItem(value, key);
  }
  return obj;
}

Use new octal syntax in comment


var agePerCentury = {};

ancestry.forEach(function(person) {
    var century = Math.ceil(person.died / 100);
    if (!(century in agePerCentury))
        agePerCentury[century] = [];

    agePerCentury[century].push(person.died - person.born);
});

for (var century in agePerCentury)
    console.log(century + ": " + average(agePerCentury[century]));

// Or, alternatively, for bonus points

function groupBy(array, groupFunc) {
    var mapping = {};
    array.forEach(function(element) {
        var mapped = groupFunc(element);
        if (!(mapped in mapping))
            mapping[mapped] = [];

        mapping[mapped].push(element);
    });
    return mapping;
}

var byCentury = groupBy(ancestry, function(person) {
    return Math.ceil(person.died / 100);
});

for (var century in byCentury) {
    var ages = byCentury[century].map(function(person) {
        return person.died - person.born;
    });
    console.log(century + ": " + average(ages));
}

function every1(array, test) {
    for (let elem of array) {
        if (!test(elem)) return false;
    }
    return true;
}

function every2(array, test) {
    const revTest = elem => !test(elem);
    return !array.some(revTest);
}

console.log(every1([1, 3, 5], n => n < 10));
// → true
console.log(every1([2, 4, 16], n => n < 10));
// → false
console.log(every1([], n => n < 10));
// → true

console.log(every2([1, 3, 5], n => n < 10));
// → true
console.log(every2([2, 4, 16], n => n < 10));
// → false
console.log(every2([], n => n < 10));
// → true

Add Chapter 05, exercise 3


'use strict';

const assert = require ('assert');
const Duplex = require('stream').Duplex;

/**
 * Creates in memory writable and readable stream
 * @return {MemDuplex} a MemDuplex instance
 */
class MemDuplex extends Duplex {
    constructor() {
        super({ highWaterMark: 8 * 1024 * 1024 });   // 8MB
        this.buffers = [];
        this.cur = 0;
        // Once writable stream is finished it will emit a finish
        // event
        this.once('finish', () => {
            this._read();
        });
    }
    _write(chunk, enc, cb) {
        assert(Buffer.isBuffer(chunk));
        this.buffers.push(chunk);
        this._read();
        cb();
    }
    _read() {
        while (this.cur < this.buffers.length) {
            this.push(this.buffers[this.cur], 'binary');
            this.cur++;
        }
        // finished is property of writable stream
        // indicating writing is done.
        // Once the writing is done and we have pushed
        // out everything buffered, we're done
        if (this.cur >= this.buffers.length && this._writableState.finished) {
            this.push(null); // End of buffer
        }
    }
}

module.exports = MemDuplex;

'use strict';

const assert = require ('assert');
const Duplex = require('stream').Duplex;

/**
 * Creates in memory writable and readable stream
 * @return {MemDuplex} a MemDuplex instance
 */
class MemDuplex extends Duplex {
    constructor() {
        super({ highWaterMark: 8 * 1024 * 1024 });   // 8MB
        this.buffers = [];
        this.cur = 0;
        // Once writable stream is finished it will emit a finish
        // event
        this.once('finish', () => {
            this._read();
        });
    }
    _write(chunk, enc, cb) {
        assert(Buffer.isBuffer(chunk));
        this.buffers.push(chunk);
        this._read();
        cb();
    }
    _read() {
        while (this.cur < this.buffers.length) {
            const pushed = this.push(this.buffers[this.cur], 'binary');
            this.cur++;
            if (!pushed) {
                break;
            }
        }
        // finished is property of writable stream
        // indicating writing is done.
        // Once the writing is done and we have pushed
        // out everything buffered, we're done
        if (this.cur >= this.buffers.length && this._writableState.finished) {
            this.push(null); // End of buffer
        }
    }
}

module.exports = MemDuplex;

Check for when push to buffer is false and break if so


const mergeDirs = require('merge-dirs').default;
const helpers = require('../../lib/helpers');
const path = require('path');
const shell = require('shelljs');
const latestVersion = require('latest-version');

module.exports = latestVersion('@storybook/react-native').then(version => {
  // copy all files from the template directory to project directory
  mergeDirs(path.resolve(__dirname, 'template/'), '.', 'overwrite');

  const packageJson = helpers.getPackageJson();

  packageJson.dependencies = packageJson.dependencies || {};
  packageJson.devDependencies = packageJson.devDependencies || {};

  packageJson.devDependencies['@storybook/react-native'] = `^${version}`;

  if (!packageJson.dependencies['react-dom'] && !packageJson.devDependencies['react-dom']) {
    packageJson.devDependencies['react-dom'] = '^15.5.4';
  }

  packageJson.scripts = packageJson.scripts || {};
  packageJson.scripts['storybook'] = 'storybook start -p 7007';

  helpers.writePackageJson(packageJson);
});

const mergeDirs = require('merge-dirs').default;
const helpers = require('../../lib/helpers');
const path = require('path');
const latestVersion = require('latest-version');

module.exports = latestVersion('@storybook/react-native').then(version => {
  // copy all files from the template directory to project directory
  mergeDirs(path.resolve(__dirname, 'template/'), '.', 'overwrite');

  const packageJson = helpers.getPackageJson();

  packageJson.dependencies = packageJson.dependencies || {};
  packageJson.devDependencies = packageJson.devDependencies || {};

  packageJson.devDependencies['@storybook/react-native'] = `^${version}`;

  if (!packageJson.dependencies['react-dom'] && !packageJson.devDependencies['react-dom']) {
    packageJson.devDependencies['react-dom'] = '^15.5.4';
  }

  packageJson.scripts = packageJson.scripts || {};
  packageJson.scripts['storybook'] = 'storybook start -p 7007';

  helpers.writePackageJson(packageJson);
});

Remove unused variable in CRNA


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

/**
 * Gets the current guild and member counts.
 *
 * @param {CommandoClient} client - The Discord.JS-Commando Client object
 * @returns {object} - An object containing two properties, guilds and members, each representing the associated counts.
 */
exports.getGuildsAndMembers = client => {
	return client.guilds.reduce((acc, guild) => {
		console.log(acc);
		acc.guilds  += 1;
		acc.members += guild.members.array().length;
		return acc;
	}, {
		guilds:  0,
		members: 0,
	});
};

exports.setGame = client => {
	let { guilds, members } = this.getGuildsAndMembers(client);
	client.user.setGame(`${client.commandPrefix || client.options.commandPrefix}help | Serving ${members} members across ${guilds} guilds`);
};

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

/**
 * Gets the current guild and member counts.
 *
 * @param {CommandoClient} client - The Discord.JS-Commando Client object
 * @returns {object} - An object containing two properties, guilds and members, each representing the associated counts.
 */
exports.getGuildsAndMembers = client => {
	return client.guilds.reduce((acc, guild) => {
		acc.guilds  += 1;
		acc.members += guild.members.array().length;
		return acc;
	}, {
		guilds:  0,
		members: 0,
	});
};

exports.setGame = client => {
	let { guilds, members } = this.getGuildsAndMembers(client);
	client.user.setGame(`${client.commandPrefix || client.options.commandPrefix}help | Serving ${members} members across ${guilds} guilds`);
};

Remove my debugging statement... again


import setupCalendar from './utils/setup';
import Calendar from '@/components/Calendar';
import DatePicker from '@/components/DatePicker';

// Export components individually
export { setupCalendar, Calendar, DatePicker };

// Installs the library as a plugin
const components = {
  Calendar,
  DatePicker,
};

// Declare install function executed by Vue.use()
export default function install(Vue, opts) {
  // Don't install more than once
  if (install.installed) return;
  install.installed = true;
  // Manually setup calendar with options
  const defaults = setupCalendar(Vue, opts);
  // Register components
  Object.keys(components).forEach(k =>
    Vue.component(`${defaults.componentPrefix}${k}`, components[k]),
  );
}

// Create module definition for Vue.use()
const plugin = {
  install,
};

// Use automatically when global Vue instance detected
let GlobalVue = null;
if (typeof window !== 'undefined') {
  GlobalVue = window.Vue;
} else if (typeof global !== 'undefined') {
  GlobalVue = global.Vue;
}
if (GlobalVue) {
  GlobalVue.use(plugin);
}

import setupCalendar from './utils/setup';
import Calendar from '@/components/Calendar';
import DatePicker from '@/components/DatePicker';

// Export components individually
export { setupCalendar, Calendar, DatePicker };

// Installs the library as a plugin
const components = {
  Calendar,
  DatePicker,
};

// Declare install function executed by Vue.use()
export default function install(Vue, opts) {
  // Don't install more than once
  if (install.installed) return;
  install.installed = true;
  // Manually setup calendar with options
  const defaults = setupCalendar(opts);
  // Register components
  Object.keys(components).forEach(k =>
    Vue.component(`${defaults.componentPrefix}${k}`, components[k]),
  );
}

// Create module definition for Vue.use()
const plugin = {
  install,
};

// Use automatically when global Vue instance detected
let GlobalVue = null;
if (typeof window !== 'undefined') {
  GlobalVue = window.Vue;
} else if (typeof global !== 'undefined') {
  GlobalVue = global.Vue;
}
if (GlobalVue) {
  GlobalVue.use(plugin);
}

Fix bug when calling `setupCalendar`


var LeaveEditorController = Ember.Controller.extend({
    args: Ember.computed.alias('model'),

    actions: {
        confirmAccept: function () {
            var args = this.get('args'),
                editorController,
                model,
                transition;

            if (Ember.isArray(args)) {
                editorController = args[0];
                transition = args[1];
                model = editorController.get('model');
            }

            if (!transition || !editorController) {
                this.notifications.showError('Sorry, there was an error in the application. Please let the Ghost team know what happened.');
                return true;
            }

            // definitely want to clear the data store and post of any unsaved, client-generated tags
            model.updateTags();

            if (model.get('isNew')) {
                // the user doesn't want to save the new, unsaved post, so delete it.
                model.deleteRecord();
            } else {
                // roll back changes on model props
                model.rollback();
            }

            // setting isDirty to false here allows willTransition on the editor route to succeed
            editorController.set('isDirty', false);

            // since the transition is now certain to complete, we can unset window.onbeforeunload here
            window.onbeforeunload = null;

            transition.retry();
        },

        confirmReject: function () {

        }
    },

    confirm: {
        accept: {
            text: 'Leave',
            buttonClass: 'button-delete'
        },
        reject: {
            text: 'Cancel',
            buttonClass: 'button'
        }
    }
});

export default LeaveEditorController;

var LeaveEditorController = Ember.Controller.extend({
    args: Ember.computed.alias('model'),

    actions: {
        confirmAccept: function () {
            var args = this.get('args'),
                editorController,
                model,
                transition;

            if (Ember.isArray(args)) {
                editorController = args[0];
                transition = args[1];
                model = editorController.get('model');
            }

            if (!transition || !editorController) {
                this.notifications.showError('Sorry, there was an error in the application. Please let the Ghost team know what happened.');
                return true;
            }

            // definitely want to clear the data store and post of any unsaved, client-generated tags
            model.updateTags();

            if (model.get('isNew')) {
                // the user doesn't want to save the new, unsaved post, so delete it.
                model.deleteRecord();
            } else {
                // roll back changes on model props
                model.rollback();
            }

            // setting isDirty to false here allows willTransition on the editor route to succeed
            editorController.set('isDirty', false);

            // since the transition is now certain to complete, we can unset window.onbeforeunload here
            window.onbeforeunload = null;

            transition.retry();
        },

        confirmReject: function () {

        }
    },

    confirm: {
        accept: {
            text: 'Leave',
            buttonClass: 'button-delete'
        },
        reject: {
            text: 'Stay',
            buttonClass: 'button'
        }
    }
});

export default LeaveEditorController;

Change text on leave modal cancel button


async function postgres_sql(args) {
/*
description("Postgres function")
base_component_id("postgres_server")
load_once_from_file(true)
only_run_on_server(true)
*/
    var config = {
      user:              args.user,
      database:          args.database,
      password:          args.password,
      host:              args.host,
      port:              args.port
    };

    console.log("postgres_server: " + JSON.stringify(args,null,2));

    var promise = new Promise(async function(returnFn) {

        var dbconnection = new postgresdb.Client(config);
        dbconnection.connect(function (err) {
          if (err) {
              console.log({error: '' + err});
              returnFn({failed: err})
          } else {
              dbconnection.query(args.sql, [], function (err, result) {
                if (err) {
                    console.log({failed: '' + err});
                } else {
                    console.log("row count: " + result.rows.length); // outputs: { name: 'brianc' }
                    if (args.limit) {
                        result.rows = result.rows.slice(0, args.limit);
                    }
                    returnFn({value: result.rows})
                };
              })

          }
        });

    })
    var ret = await promise

    return ret
}

async function postgres_sql(args) {
/*
description("Postgres function")
base_component_id("postgres_server")
load_once_from_file(true)
only_run_on_server(true)
*/
    var config = {
      user:              args.user,
      database:          args.database,
      password:          args.password,
      host:              args.host,
      port:              args.port
    };

    console.log("postgres_server: " + JSON.stringify(args,null,2));

    var promise = new Promise(async function(returnFn) {

        var dbconnection = new postgresdb.Client(config);
        dbconnection.connect(function (err) {
          if (err) {
              console.log({error: '' + err});
              returnFn({failed: err})
          } else {
              var useSql = args.sql
              if (args.get_tables) {
                  useSql = "SELECT tablename as name FROM pg_catalog.pg_tables where schemaname = 'public';"
              }
              dbconnection.query(useSql, [], function (err, result) {
                if (err) {
                    console.log({failed: '' + err});
                } else {
                    console.log("row count: " + result.rows.length); // outputs: { name: 'brianc' }
                    if (args.limit) {
                        result.rows = result.rows.slice(0, args.limit);
                    }
                    returnFn({value: result.rows})
                };
              })

          }
        });

    })
    var ret = await promise

    return ret
}

Allow Postgres DB driver to return the list of tables


#!/usr/bin/env node

var assert = require('assert');
var pagination = require('pagination');
var SearchPaginator = pagination.SearchPaginator;

var objectList = [
  { name: 'Taro', age: 11 },
  { name: 'Jiro', age: 12 },
  { name: 'Saburo', age: 13 },
  { name: 'Shiro', age: 14 },
  { name: 'Goro', age: 15 },
];

var paginator, paginated;

paginator = new SearchPaginator({
  totalResult: objectList.length,
  rowsPerPage: 2,
  current: 1,
});
paginated = paginator.getPaginationData();

console.log(paginated);
assert.strictEqual(paginated.pageCount, 3);
assert.strictEqual(paginated.fromResult, 1);
assert.strictEqual(paginated.toResult, 2);
assert.strictEqual(paginated.previous, null);
assert.strictEqual(paginated.next, 2);
assert.strictEqual(paginated.first, null);
assert.strictEqual(paginated.last, 3);

#!/usr/bin/env node

var assert = require('assert');
var pagination = require('pagination');
var SearchPaginator = pagination.SearchPaginator;

var objectList = [
  { name: 'Taro', age: 11 },
  { name: 'Jiro', age: 12 },
  { name: 'Saburo', age: 13 },
  { name: 'Shiro', age: 14 },
  { name: 'Goro', age: 15 },
];

var paginator, paginated;

//
// basic usage
//
paginator = new SearchPaginator({
  totalResult: objectList.length,
  rowsPerPage: 2,
  current: 1,
});
paginated = paginator.getPaginationData();

//console.log(paginated);
assert.strictEqual(paginated.pageCount, 3);
assert.strictEqual(paginated.fromResult, 1);
assert.strictEqual(paginated.toResult, 2);
assert.strictEqual(paginated.previous, null);
assert.strictEqual(paginated.next, 2);
assert.strictEqual(paginated.first, null);
assert.strictEqual(paginated.last, 3);

//
// set current page number to out of range
//
paginator = new SearchPaginator({
  totalResult: objectList.length,
  rowsPerPage: 2,
  current: 100,
});
paginated = paginator.getPaginationData();
assert.strictEqual(paginated.current, 3);  // Not overflow

paginator = new SearchPaginator({
  totalResult: objectList.length,
  rowsPerPage: 2,
  current: -100,
});
paginated = paginator.getPaginationData();
assert.strictEqual(paginated.current, -100);  // Overflow!

Update a sample of pagination


$(document).ready(function() {
  $("#splash").hide();
  $("footer").hide();
  if ($("#splash").length > 0) {
    $("#splash").bind("load", function () {
      $("#splash").fadeIn(3000);
      $("footer").delay(1500).fadeIn(3000);
    });
    $("#splash").fadeIn(3000);
    $("footer").delay(1500).fadeIn(3000);
  } else {
    $("footer").delay(1500).fadeIn(3000);
  }
  $("a[class='tooltip-hover']").tooltip();
  $("a[class='tooltip-click']").tooltip({
    trigger: "click"
  });
  $("a[class^='tooltip-']").attr("href", "javascript:void(0)");
  $("a[href$='.jpg'],a[href$='.png']").fancybox({
    padding: 10,
    margin: 50,
    loop: false,
    helpers : {
      title : {
        type: "over"
      },
      overlay : {
        showEarly: false,
        css : {
          "background" : "rgba(25, 25, 25, 0.80)"
        }
      }
    }
  });
  $(".fancybox-media").fancybox({
    padding: 10,
    margin: 50,
    loop: false,
    helpers : {
      media : {},
      title : {
        type: "float"
      },
      overlay : {
        showEarly: false,
        css : {
          "background" : "rgba(25, 25, 25, 0.80)"
        }
      }
    }
  });
});

$(document).ready(function() {
  $("#splash").hide();
  $("footer").hide();
  if ($("#splash").length > 0) {
    $("#splash").bind("load", function () {
      $("#splash").fadeIn(3000);
      $("footer").delay(1500).fadeIn(3000);
    });
  } else {
    $("footer").delay(1500).fadeIn(3000);
  }
  $("a[class='tooltip-hover']").tooltip();
  $("a[class='tooltip-click']").tooltip({
    trigger: "click"
  });
  $("a[class^='tooltip-']").attr("href", "javascript:void(0)");
  $("a[href$='.jpg'],a[href$='.png']").fancybox({
    padding: 10,
    margin: 50,
    loop: false,
    helpers : {
      title : {
        type: "over"
      },
      overlay : {
        showEarly: false,
        css : {
          "background" : "rgba(25, 25, 25, 0.80)"
        }
      }
    }
  });
  $(".fancybox-media").fancybox({
    padding: 10,
    margin: 50,
    loop: false,
    helpers : {
      media : {},
      title : {
        type: "float"
      },
      overlay : {
        showEarly: false,
        css : {
          "background" : "rgba(25, 25, 25, 0.80)"
        }
      }
    }
  });
});

Revert "Attempt to fix fading of splash image"


export default {
  experimentsURL: '/api/experiments.json',
  usageCountsURL: '/api/experiments/usage_counts.json'
};

export default {
  experimentsURL: '/api/experiments.json',
  usageCountsURL: 'https://analysis-output.telemetry.mozilla.org/testpilot/data/installation-counts/latest.json'
};

Switch to Telemetry data for experiment usage counts


define(function (require) {
    'use strict';
    var $ = require('jquery');
    var monaco = require('monaco');
    var cpp = require('vs/basic-languages/src/cpp');

    // We need to create a new definition for cpp so we can remove invalid keywords

    function definition() {
        var cppp = $.extend(true, {}, cpp.language); // deep copy

        function removeKeyword(keyword) {
            var index = cppp.keywords.indexOf(keyword);
            if (index > -1) {
                cppp.keywords.splice(index, 1);
            }
        }

        removeKeyword("array");
        removeKeyword("in");
        removeKeyword("interface");
        removeKeyword("ref");

        return cppp;
    }

    monaco.languages.register({id: 'cppp'});
    monaco.languages.setLanguageConfiguration('cppp', cpp.conf);
    monaco.languages.setMonarchTokensProvider('cppp', definition());
});

define(function (require) {
    'use strict';
    var $ = require('jquery');
    var monaco = require('monaco');
    var cpp = require('vs/basic-languages/src/cpp');

    // We need to create a new definition for cpp so we can remove invalid keywords

    function definition() {
        var cppp = $.extend(true, {}, cpp.language); // deep copy

        function removeKeyword(keyword) {
            var index = cppp.keywords.indexOf(keyword);
            if (index > -1) {
                cppp.keywords.splice(index, 1);
            }
        }

        function removeKeywords(keywords) {
            for (var i = 0; i < keywords.length; ++i) {
                removeKeyword(keywords[i]);
            }
        }

        function addKeywords(keywords) {
            // (Ruben) Done one by one as if you just push them all, Monaco complains that they're not strings, but as
            // far as I can tell, they indeed are all strings. This somehow fixes it. If you know how to fix it, plz go
            for (var i = 0; i < keywords.length; ++i) {
                cppp.keywords.push(keywords[i]);
            }
        }

        // We remove everything that's not an identifier, underscore reserved name and not an official C++ keyword...
        removeKeywords(["abstract", "amp", "array", "cpu", "delegate", "each", "event", "final", "finally", "gcnew",
            "generic", "in", "initonly", "interface", "interior_ptr", "internal", "literal", "partial", "pascal",
            "pin_ptr", "property", "ref", "restrict", "safe_cast", "sealed", "title_static", "where"]);

        addKeywords(["alignas", "alignof", "and", "and_eq", "asm", "bitand", "bitor", "char16_t", "char32_t", "compl",
            "not", "not_eq", "or", "or_eq", "xor", "xor_eq"]);

        return cppp;
    }

    monaco.languages.register({id: 'cppp'});
    monaco.languages.setLanguageConfiguration('cppp', cpp.conf);
    monaco.languages.setMonarchTokensProvider('cppp', definition());
});

Remove non-standard keywords and add missing ones


(function initOverlayWindow() {
  function selectFolderOnInit(initialUri) {
    var startupFolder = GetMsgFolderFromUri("mailbox://nobody@Local%20Folders");
    if (startupFolder) {
      initialUri = startupFolder.URI;
      var folderTree = document.getElementById("folderTree");
      if (window.gFolderTreeView)
        gFolderTreeView.selectFolder(startupFolder);
    }
  }
  window.loadStartFolder = selectFolderOnInit;
})();

function startup() {
  // Set the time zone to UTC.
  var env = Components.classes["@mozilla.org/process/environment;1"]
                            .getService(Components.interfaces.nsIEnvironment);
  env.set('TZ', 'UTC');

  var prefs = Components.classes["@mozilla.org/preferences-service;1"]
                    .getService(Components.interfaces.nsIPrefBranch);

  var myPanel = document.getElementById("my-panel");
  var strbundle = document.getElementById("strings");
  if (prefs.getBoolPref("extensions.torbirdy.protected"))
  {
    var type = prefs.getIntPref("extensions.torbirdy.proxy");
    myPanel.style.color = "green";
    // Tor.
    if (type === 0)
    {
      myPanel.label = strbundle.getString("torbirdy.enabled.tor");
    }
    // JonDo.
    if (type === 1)
    {
      myPanel.label = strbundle.getString("torbirdy.enabled.jondo");
    }
    // Custom.
    if (type === 2)
    {
      myPanel.label = strbundle.getString("torbirdy.enabled.custom");
    }
  } else {
    myPanel.label = strbundle.getString("torbirdy.enabled.disabled");
    myPanel.style.color = "red";
  }
}

window.addEventListener("load", startup, false);

Select the Local Folders on startup instead of last selected account


var map = require('through2-map');
var fs = require('fs');

module.exports.create = function create_json_parse_stream(dataDirectory) {
  return map.obj(function(record) {
    try {
      return JSON.parse(fs.readFileSync(dataDirectory + record.path));
    } catch (err) {
      console.error('exception on %s:', record.path, err);
      console.error('Inability to parse JSON usually means that WOF has been cloned ' +
                    'without using git-lfs, please see instructions here: ' +
                    'https://github.com/whosonfirst/whosonfirst-data#git-and-large-files');
      return {};
    }
  });
};

var fs = require('fs');
var parallelStream = require('pelias-parallel-stream');

var maxInFlight = 10;

module.exports.create = function create_json_parse_stream(dataDirectory) {
  return parallelStream(maxInFlight, function(record, enc, next) {
    fs.readFile(dataDirectory + record.path, function(err, data) {
      if (err) {
        next(err);
      } else {
        try {
          var object = JSON.parse(data);
          next(null, object);
        } catch (parse_err) {
          console.error('exception on %s:', record.path, parse_err);
          console.error('Inability to parse JSON usually means that WOF has been cloned ' +
                        'without using git-lfs, please see instructions here: ' +
                        'https://github.com/whosonfirst/whosonfirst-data#git-and-large-files');
          next(null, {});
        }
      }
    });
  });
};

Load JSON files in parallel


var fs = require('fs');

function qmlize(text) {
	// replace reserved keyword as with "as"
	text = text.replace(/([\,\{]\s*)(as)(\s*:)/gm, '$1"$2"$3')
	text = text.replace(/(new\s+[^\(\)\{\}\s;]+)(\s*;)/gm, '$1()$2')
	text = text.replace(/(new\s+[^\(\)\{\}\s;]+)(\s*\})/gm, '$1();$2')
	text = text.replace(/(\{\s*break)(\s*\})/gm, '$1;$2')
	return text;
}

(function () {
	console.log(process.argv);
	if (process.argv.length == 4) {
		var data = fs.readFileSync(process.argv[2], {encoding: 'utf8'});
		fs.writeFileSync(process.argv[3], qmlize(data), {encoding: 'utf8'});
	}
})();

/*
 * qmlizer.js - fix the output of uglify so that it works properly in
 * Qt/qml.
 *
 * Copyright © 2018, LGE, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
var fs = require('fs');

function qmlize(text) {
	// replace reserved keyword as with "as"
	text = text.replace(/([\,\{]\s*)(as)(\s*:)/gm, '$1"$2"$3')
	text = text.replace(/(new\s+[^\(\)\{\}\s;,]+)(\s*[;,])/gm, '$1()$2')
	text = text.replace(/(new\s+[^\(\)\{\}\s;,]+)(\s*\})/gm, '$1();$2')
	text = text.replace(/(\{\s*break)(\s*\})/gm, '$1;$2')
	return text;
}

(function () {
	console.log(process.argv);
	if (process.argv.length == 4) {
		var data = fs.readFileSync(process.argv[2], {encoding: 'utf8'});
		fs.writeFileSync(process.argv[3], qmlize(data), {encoding: 'utf8'});
	}
})();

Handle the case where statements end in comma instead of semi-colon


var express = require('express');
var User = require('../schemas/userSchema.js');

var app = express();

app.get('/users', function (req, res, next) {
  if (req.isAuthenticated()) {
    res.json({
      "users": [req.user]
    });
  } else {
    res.json({
      "users": [{
        _id: "anonymous user"
      }]
    })
  }
});

app.put('/users/:id', function (req, res, next) {
  if (!req.isAuthenticated()) {
    res.send(401, 'You must be logged in to join a project');
  }

  User.findById(req.params.id).exec().then(function (user) {
    user.projects = req.body.user.projects;
    user.save();

    res.json({
      "user": user
    });
  }, next);
});

module.exports = app;

var express = require('express');
var User = require('../schemas/userSchema.js');

var app = express();

app.get('/users', function (req, res, next) {
  if (req.isAuthenticated()) {
    res.json({
      "users": [req.user]
    });
  } else {
    res.json({
      "users": [{
        _id: "anonymous user",
        isAnonymous: true
      }]
    })
  }
});

app.put('/users/:id', function (req, res, next) {
  if (!req.isAuthenticated()) {
    res.send(401, 'You must be logged in to join a project');
  }

  User.findById(req.params.id).exec().then(function (user) {
    user.projects = req.body.user.projects;
    user.save();

    res.json({
      "user": user
    });
  }, next);
});

module.exports = app;

Add isAnonymous property to anonymous user


;(function() {
  var div, body = document.body
  if (body.style.flex == null && document.body.style.webkitFlex == null) {
    div = document.createElement("div")
    div.className = "Error"
    div.innerHTML = "Your browser does not support Flexbox. Parts of this site may not appear as expected."
    body.insertBefore(div, body.firstChild)
  }
}())

;(function(body, div) {
  if (body.style.flex == null && body.style.webkitFlex == null) {
    div = document.createElement("div")
    div.className = "Error"
    div.innerHTML = "Your browser does not support Flexbox. Parts of this site may not appear as expected."
    body.insertBefore(div, body.firstChild)
  }
}(document.body))

Use local body reference instead of document.body.


'use strict'

const ExtDate = require('./src/date')
const Bitmask = require('./src/bitmask')

const { parse } = require('./src/parser')

const types = [
  'Date', 'Year', 'Season', 'Interval', 'Set', 'List', 'Century', 'Decade'
]

function edtf(...args) {
  if (!args.length) return new ExtDate()

  const res = parse(...args)
  return new ExtDate(res)
  //return new this[res.type](res)
}

module.exports = Object.assign(edtf, {
  Date: ExtDate,
  Bitmask,
  parse,
  types
})

'use strict'

const ExtDate = require('./src/date')
const Bitmask = require('./src/bitmask')

const { parse } = require('./src/parser')

const types = [
  'Date', 'Year', 'Season', 'Interval', 'Set', 'List', 'Century', 'Decade'
]

function edtf(...args) {
  if (!args.length) return new ExtDate()

  const res = parse(...args)
  return new edtf[res.type](res)
}

module.exports = Object.assign(edtf, {
  Date: ExtDate,
  Bitmask,
  parse,
  types
})

Use parsed types for creating objects


var Transform = require('broccoli-transform');
var RSVP = require('rsvp');
var requirejs = require('requirejs');
var mkdirp = require('mkdirp');
var fs = require('fs');
var path = require('path');
var _ = require('lodash');

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

  this.inputTree = inputTree;
  this.options = options || {};
}

RequireJsFilter.prototype = Object.create(Transform.prototype);
RequireJsFilter.prototype.constructor = RequireJsFilter;

RequireJsFilter.prototype.transform = function (srcDir, destDir) {
  var options = this.options;
  var requirejs_options = options.requirejs || {};

  return new RSVP.Promise(function(resolve, reject) {
    var tmp_options = _.clone(requirejs_options);

    if (requirejs_options.baseUrl) {
        tmp_options.baseUrl = path.join(srcDir, requirejs_options.baseUrl);
    } else {
        tmp_options.baseUrl = srcDir;
    }

    if (requirejs_options.mainConfigFile) {
      tmp_options.mainConfigFile = path.join(srcDir, requirejs_options.mainConfigFile);
    }

    tmp_options.out = path.join(destDir,requirejs_options.out);

    requirejs.optimize(tmp_options, function (buildResponse) {
      resolve(destDir);
    });
  }.bind(this));
};

module.exports = RequireJsFilter;

var Transform = require('broccoli-transform');
var RSVP = require('rsvp');
var requirejs = require('requirejs');
var mkdirp = require('mkdirp');
var fs = require('fs');
var path = require('path');
var _ = require('lodash');

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

  this.inputTree = inputTree;
  this.options = options || {};
}

RequireJsFilter.prototype = Object.create(Transform.prototype);
RequireJsFilter.prototype.constructor = RequireJsFilter;

RequireJsFilter.prototype.transform = function (srcDir, destDir) {
  var options = this.options;
  var requirejs_options = options.requirejs || {};

  return new RSVP.Promise(function(resolve, reject) {
    var tmp_options = _.clone(requirejs_options);

    if (requirejs_options.baseUrl) {
        tmp_options.baseUrl = path.join(srcDir, requirejs_options.baseUrl);
    } else {
        tmp_options.baseUrl = srcDir;
    }

    if (requirejs_options.mainConfigFile) {
      tmp_options.mainConfigFile = path.join(srcDir, requirejs_options.mainConfigFile);
    }

    if (requirejs_options.exclude) {
      tmp_options.exclude = requirejs_options.exclude;
    }

    tmp_options.out = path.join(destDir,requirejs_options.out);

    requirejs.optimize(tmp_options, function (buildResponse) {
      resolve(destDir);
    });
  }.bind(this));
};

module.exports = RequireJsFilter;

Support for the exclude option


'use strict';

exports.register = function (plugin, options, next) {

  plugin.ext('onPreResponse', function (request, reply) {
    var res = request.response;
    if (res.source && typeof res.source.then === 'function') {
      return res.source
        .then(function (value) {
          res.source = value;
          return res;
        })
        .catch(function (err) {
          throw err;
        })
        .then(reply, reply);
    }
    reply();
  });

  next();

};

exports.register.attributes = {
  pkg: require('./package.json')
}

'use strict';

exports.register = function (plugin, options, next) {

  plugin.ext('onPreResponse', function (request, reply) {
    var res = request.response;
    if (res.source && typeof res.source.then === 'function') {
      return res.source
        .then(function (value) {
          res.source = value;
          return res;
        })
        .then(reply, reply);
    }
    reply();
  });

  next();

};

exports.register.attributes = {
  pkg: require('./package.json')
}

Remove extraneous code from debugging


var lerp = require('lerp-array');

function interpolateArrays(arrays, t) {
    if (t >= 1) {
        return arrays[arrays.length - 1];
    }
    if (arrays.length == 1) {
        return arrays[0];
    }
    var numStops = arrays.length - 1;
    var stopF = t * numStops;
    var stop = Math.floor(stopF);
    var k = stopF - stop;
    return lerp(arrays[stop], arrays[stop+1], k);
}

module.exports = interpolateArrays;

var lerp = require('lerp-array');

function interpolateArrays(arrays, t, out) {
    if (t >= 1) {
        return arrays[arrays.length - 1];
    }
    if (arrays.length == 1) {
        return arrays[0];
    }
    var numStops = arrays.length - 1;
    var stopF = t * numStops;
    var stop = Math.floor(stopF);
    var k = stopF - stop;
    return lerp(arrays[stop], arrays[stop+1], k, out);
}

module.exports = interpolateArrays;

Add out parameter to avoid GC garbage


var es = require('event-stream');
var gutil = require('gulp-util');
var path = require('path');
var ect = require('ect');

module.exports = function (opt) {
  opt = opt || {};
  if (!opt.ext) opt.ext = '.ect';
  if (!opt.outExt) opt.outExt = '.html';

  return es.map(function (file, callback) {
    try {
      var filePath = file.base;
      var fileName = gutil.replaceExtension(path.basename(file.path), "");
      var html = ect({
        root: filePath,
        ext: opt.ext
      });
      html.render(fileName, function (error, html) {
        file.contents = new Buffer(html);
        file.path = gutil.replaceExtension(file.path, opt.outExt);
      });
    } catch (e) {
      console.warn('Error gulp-ect: ' + e.message);
    }
    callback(null, file);
  });
};

var es = require('event-stream');
var gutil = require('gulp-util');
var path = require('path');
var ect = require('ect');

module.exports = function (opt) {
  opt = opt || {};
  if (!opt.ext) opt.ext = '.ect';
  if (!opt.outExt) opt.outExt = '.html';

  return es.map(function (file, callback) {
    try {
      var filePath = file.base;
      var fileName = gutil.replaceExtension(path.basename(file.path), "");
      var html = ect({
        root: filePath,
        ext: opt.ext
      });
      html.render(fileName, function (error, html) {
        file.contents = new Buffer(html);
        file.path = gutil.replaceExtension(file.path, opt.outExt);
      });
    } catch (e) {
      gutil.log(gutil.colors.red('Error gulp-ect: ' + e.message));
    }
    callback(null, file);
  });
};

Use gulp-util.log instead of console.warn


var pkgs = ['item_paginator', 'search_paginator', 'template_paginator', 'template'];
var pagination = require('./lib/pagination.js');
var util = require('util');
require('./lib/item_paginator')(pagination, util);
require('./lib/search_paginator')(pagination, util);
require('./lib/template_paginator')(pagination, util);
require('./lib/template')(pagination, util);

module.exports = pagination;

var util = require('util');
var pagination = require('./lib/pagination');
require('./lib/item_paginator').module(pagination, util);
require('./lib/search_paginator').module(pagination, util);
require('./lib/template_paginator').module(pagination, util);
require('./lib/template').module(pagination, util);

module.exports = pagination;

Fix bugs in previous commit


'use strict';

/**
 * @ngdoc function
 * @name ocwUiApp.controller:DatasetSelectCtrl
 * @description
 * # DatasetSelectCtrl
 * Controller of the ocwUiApp
 */
angular.module('ocwUiApp')
  .controller('DatasetSelectCtrl', ['$scope', 'selectedDatasetInformation',
    function($scope, selectedDatasetInformation) {
      // Grab a copy of the datasets so we can display a count to the user!
      $scope.datasetCount = selectedDatasetInformation.getDatasets();

      $scope.shouldDisableClearButton = function() {
        return (selectedDatasetInformation.getDatasetCount() === 0);
      };

      $scope.clearDatasets = function() {
        selectedDatasetInformation.clearDatasets();
      };

      $scope.open = function () {
        $scope.datasetSelect = true;
      };

      $scope.close = function () {
        $scope.datasetSelect = false;
      };

      $scope.opts = {
        backdropFade: true,
        dialogFade: true,
      };

      $scope.templates = [
        {title:'Local File', url: 'partials/selectObservation.html'},
        {title:'RCMED', url: 'partials/selectRcmed.html'},
        {title:'ESG', disabled: true}
      ];

      $scope.template = $scope.templates[0];
    }
  ]);

'use strict';

/**
 * @ngdoc function
 * @name ocwUiApp.controller:DatasetSelectCtrl
 * @description
 * # DatasetSelectCtrl
 * Controller of the ocwUiApp
 */
angular.module('ocwUiApp')
  .controller('DatasetSelectCtrl', ['$scope', 'selectedDatasetInformation',
    function($scope, selectedDatasetInformation) {
      // Grab a copy of the datasets so we can display a count to the user!
      $scope.datasetCount = selectedDatasetInformation.getDatasets();

      $scope.shouldDisableClearButton = function() {
        return (selectedDatasetInformation.getDatasetCount() === 0);
      };

      $scope.clearDatasets = function() {
        selectedDatasetInformation.clearDatasets();
      };

      $scope.open = function () {
        $scope.datasetSelect = true;
      };

      $scope.close = function () {
        $scope.datasetSelect = false;
      };

      $scope.opts = {
        backdropFade: true,
        dialogFade: true,
      };

      $scope.templates = [
        {title:'Local File', url: 'views/selectObservation.html'},
        {title:'RCMED', url: 'views/selectRcmed.html'},
        {title:'ESG', disabled: true}
      ];

      $scope.template = $scope.templates[0];
    }
  ]);

Fix view routing in DatasetSelectCtrl


/*jshint node:true*/
/**
 * Strips away sensitive data from gmeConfig, use before sending it to the client.
 * @author pmeijer / https://github.com/pmeijer
 */

function getClientConfig(gmeConfig) {
    'use strict';
    var clientConfig = JSON.parse(JSON.stringify(gmeConfig));

    delete clientConfig.server.sessionCookieSecret;
    delete clientConfig.server.https.certificateFile;
    delete clientConfig.server.https.keyFile;
    delete clientConfig.executor.nonce;
    delete clientConfig.mongo;
    delete clientConfig.blob;

    clientConfig.storage.cache = clientCacheSize;

    return clientConfig;
}

module.exports = getClientConfig;

/*jshint node:true*/
/**
 * Strips away sensitive data from gmeConfig, use before sending it to the client.
 * @author pmeijer / https://github.com/pmeijer
 */

function getClientConfig(gmeConfig) {
    'use strict';
    var clientConfig = JSON.parse(JSON.stringify(gmeConfig));

    delete clientConfig.server.sessionCookieSecret;
    delete clientConfig.server.https.certificateFile;
    delete clientConfig.server.https.keyFile;
    delete clientConfig.executor.nonce;
    delete clientConfig.mongo;
    delete clientConfig.blob;

    clientConfig.storage.cache = clientConfig.storage.clientCacheSize;

    return clientConfig;
}

module.exports = getClientConfig;

Allow different storage.cache to be configured for client


(function() {
  "use strict";
/* global define, Ember */
define('ember', [], function() {
  "use strict";

  return {
    'default': Ember
  };
});

define('ember/computed', [], function() {
  "use strict";

  var exports = {
    'default': Ember.computed
  };

  for (var key in Ember.computed) {
    exports[key] = Ember.computed[key];
  }

  return exports;
});

define('ember-data', [], function() {
  "use strict";

  return {
    'default': DS
  };
});

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

  return {
    'default': jQuery
  };
});

})();

(function() {
/* globals define, Ember, DS, jQuery */

  var shims = {
    'ember': {
      'default': Ember
    },
    'ember/computed': {
      'default': Ember.computed
    },

    'ember-data': {
      'default': DS
    },
    'jquery': {
      'default': jQuery
    }
  };

  // populate `ember/computed` named exports
  for (var key in Ember.computed) {
    shims['ember/computed'][key] = Ember.computed[key];
  }

  for (var moduleName in shims) {
    define(moduleName, [], function() {
      'use strict';

      return shims[moduleName];
    });
  }
})();

Update to simpler module generation.


const fs = require('fs')
const path = require('path')

class FileService {
  get scripts() {
    const folderContent = fs.readdirSync(path.join(this.configService.folderPath, 'scripts'))
    const authorizedExtensions = this.configService.scriptExtension

    return folderContent
      .filter(element => {
        const foundResults = []
        for (const extension of authorizedExtensions) {
          foundResults.push(element.includes(extension))
        }

        return foundResults.filter(element => element).length > 0
      })
      .map(element => {
        const [scriptName] = element.split('.')
        const scriptSlug = scriptName
          .toLowerCase()
          .replace(/ /g,'-')
          .replace(/[^\w-]+/g,'')

        return {
          script: scriptSlug,
          file: element
        }
      })
  }

  get modules() {}

  constructor(configService) {
    this.configService = configService

    this._scripts = []
    this._modules = []
  }
}

module.exports = exports = { FileService }

const fs = require('fs')
const path = require('path')

class FileService {
  get scripts() {
    const folderContent = fs.readdirSync(path.join(this.configService.folderPath, 'scripts'))
    const authorizedExtensions = this.configService.scriptExtension

    return folderContent
      .filter(element => {
        const foundResults = []
        for (const extension of authorizedExtensions) {
          foundResults.push(element.includes(extension))
        }

        return foundResults.filter(element => element).length > 0
      })
      .map(element => {
        const [scriptName] = element.split('.')
        const scriptSlug = scriptName
          .toLowerCase()
          .replace(/ /g,'-')
          .replace(/[^\w-]+/g,'')

        return {
          script: scriptSlug,
          file : element,
          path: path.join(this.configService.folderPath, 'scripts', element)
        }
      })
  }

  get modules() {}

  constructor(configService) {
    this.configService = configService

    this._scripts = []
    this._modules = []
  }
}

module.exports = exports = { FileService }

Add path to script in FileService


'use strict';

// this Babel plugin removes configuration comments such as:
//   <!-- template-lint triple-curlies=false -->
//   <!-- template-lint enabled=false -->

const AstNodeInfo = require('ember-template-lint/lib/helpers/ast-node-info');

module.exports = function() {
  function RemoveConfigurationHtmlCommentsPlugin() {}

  RemoveConfigurationHtmlCommentsPlugin.prototype.transform = function(ast) {
    let walker = new this.syntax.Walker();
    let bodyEntry;

    walker.visit(ast, node => {
      if (node.type === 'Program') {
        for (let i = 0; i < node.body.length; i++) {
          bodyEntry = node.body[i];

          if(AstNodeInfo.isConfigurationHtmlComment(bodyEntry)) {
            // remove the entry
            node.body.splice(i, 1);
          }
        }
      }
    });

    return ast;
  };

  return RemoveConfigurationHtmlCommentsPlugin;
};

'use strict';

// this Babel plugin removes configuration comments such as:
//   <!-- template-lint triple-curlies=false -->
//   <!-- template-lint enabled=false -->

const AstNodeInfo = require('ember-template-lint/lib/helpers/ast-node-info');

module.exports = function() {
  function RemoveConfigurationHtmlCommentsPlugin() {}

  RemoveConfigurationHtmlCommentsPlugin.prototype.transform = function(ast) {
    let walker = new this.syntax.Walker();
    let bodyEntry;

    walker.visit(ast, node => {
      if (node.type === 'Program') {
        for (let i = 0; i < node.body.length; i++) {
          bodyEntry = node.body[i];

          if(AstNodeInfo.isConfigurationHtmlComment(bodyEntry)) {
            // remove the entry
            node.body.splice(i, 1);
          }
        }
      }
    });

    return ast;
  };

  RemoveConfigurationHtmlCommentsPlugin.parallelBabel = {
    requireFile: __filename,
    buildUsing: 'self',
  };

  return RemoveConfigurationHtmlCommentsPlugin;
};

module.exports.self = function(){ return module.exports(); };

Support usage inside paralle babel inside inline-hbs


const AbstractHandler = require('./AbstractHandler');
const Constants = require('../../../../util/Constants');

class ResumedHandler extends AbstractHandler {
  handle(packet) {
    const client = this.packetManager.client;
    const ws = client.ws.connection;

    ws._trace = packet.d._trace;

    ws.status = Constants.Status.READY;
    this.packetManager.handleQueue();

    const replayed = ws.sequence - ws.closeSequence;

    client.emit('debug', `RESUMED ${ws._trace.join(' -> ')} | replayed ${replayed} events. `);
    client.emit('resume', replayed);
    ws.heartbeat();
  }
}

/**
 * Emitted whenever a websocket resumes
 * @event Client#resume
 * @param {number} replayed Number of events that were replayed
 */

module.exports = ResumedHandler;

const AbstractHandler = require('./AbstractHandler');
const Constants = require('../../../../util/Constants');

class ResumedHandler extends AbstractHandler {
  handle(packet) {
    const client = this.packetManager.client;
    const ws = client.ws.connection;

    ws._trace = packet.d._trace;

    ws.status = Constants.Status.READY;
    this.packetManager.handleQueue();

    const replayed = ws.sequence - ws.closeSequence;

    ws.debug(`RESUMED ${ws._trace.join(' -> ')} | replayed ${replayed} events.`);
    client.emit('resume', replayed);
    ws.heartbeat();
  }
}

/**
 * Emitted whenever a websocket resumes
 * @event Client#resume
 * @param {number} replayed Number of events that were replayed
 */

module.exports = ResumedHandler;

Debug resume from connection not Client


import { foreach } from './src/foreach.js';

export var bindings = {
  foreach: foreach
};

// By default, foreach will be async.
foreach.setSync(false);

Set to async mode by default


#! /usr/bin/env node
/* eslint import/no-dynamic-require: 0 */

const log = require('winston');
const inquirer = require('inquirer');
const search = require('./lib/search');
const exec = require('./lib/exec');

const packageJSON = require(`${process.cwd()}/package.json`);
const commands = Object.keys(packageJSON.scripts).map(command => ({ command, humanized: command.split(':').join(' ') }));
const searchTerm = process.argv.slice(2).join(' ');

log.remove(log.transports.Console);
log.add(log.transports.Console, { colorize: true });

const prompt = () => {
  inquirer.prompt({
    message: 'Choose a command to run:',
    type: 'list',
    name: 'command',
    pageSize: 100,
    choices: commands.map(c => c.command),
  })
  .then((answer) => {
    exec(answer.command);
  });
};

const fuseSearch = () => {
  const result = search(commands, searchTerm);

  if (result.length > 0) {
    const command = result[0].item.command;
    exec(command);
  } else {
    log.error(`There are no results that match "${searchTerm}"`);
    process.exit(1);
  }
};

if (!searchTerm) {
  prompt();
} else {
  fuseSearch();
}

#! /usr/bin/env node
/* eslint import/no-dynamic-require: 0 */

const log = require('winston');
const inquirer = require('inquirer');
const search = require('./lib/search');
const exec = require('./lib/exec');

const packageJSON = require(`${process.cwd()}/package.json`);
const commands = Object.keys(packageJSON.scripts).map(command => ({ command, humanized: command.split(':').join(' ') }));
const searchTerm = process.argv.slice(2).join(' ');

log.remove(log.transports.Console);
log.add(log.transports.Console, { colorize: true });

const prompt = () => {
  inquirer.prompt({
    message: 'Choose a command to run:',
    type: 'rawlist',
    name: 'command',
    pageSize: 100,
    choices: commands.map(c => c.command),
  })
  .then((answer) => {
    exec(answer.command);
  });
};

const fuseSearch = () => {
  const result = search(commands, searchTerm);

  if (result.length > 0) {
    const command = result[0].item.command;
    exec(command);
  } else {
    log.error(`There are no results that match "${searchTerm}"`);
    process.exit(1);
  }
};

if (!searchTerm) {
  prompt();
} else {
  fuseSearch();
}

Change list type for a faster script selection


'use strict';

const SlackBot = require('./src/SlackBot');
const GitHubApiClient = require("./src/GitHubApiClient");
const PullRequests = require('./src/PullRequests');
const _ = require('lodash');

const controller = new SlackBot().getController();

controller.hears("^ls author:([^\s]+) owner:([^\s]+)",["direct_message","direct_mention","mention"], (bot, message) => {
  const authors = message.match[1].split(',');
  const owner = message.match[2];

  const client = new GitHubApiClient();

  client.getAllPullRequests(authors).then((prs) => {
    bot.startConversation(message, (err, convo) => {
      convo.say(':memo: Review waiting list!');
      _.each(new PullRequests(prs, owner).convertToSlackMessages(), (pr) => convo.say(pr));
      convo.next()
    })
  });
});

'use strict';

const SlackBot = require('./src/SlackBot');
const GitHubApiClient = require("./src/GitHubApiClient");
const PullRequests = require('./src/PullRequests');
const _ = require('lodash');

const controller = new SlackBot().getController();

controller.hears("^ls (.+)",["direct_message","direct_mention","mention"], (bot, message) => {
  const match = message.match[1].match(/author:([^\s]+) owner:([^\s]+)/);
  const authors = match[1].split(',');
  const owner = match[2];

  const client = new GitHubApiClient();

  client.getAllPullRequests(authors).then((prs) => {
    bot.startConversation(message, (err, convo) => {
      convo.say(':memo: Review waiting list!');
      _.each(new PullRequests(prs, owner).convertToSlackMessages(), (pr) => convo.say(pr));
      convo.next()
    })
  });
});

Check arguments after controller fetches message


export const properties = {
    orientation: "vertical",
    stroke: {
        width: "1px"
    }
}

export const properties = {
    orientation: "vertical",
    stroke: {
        width: "1px"
    },
    legend: {
        show: false
    }
}

Hide BarChart legend by default


import check from './support/check';

describe('objects', () => {
  it('adds curly braces immediately around a single-line object', () => {
    check(`
      a b: c, d: e
    `, `
      a({b: c, d: e});
    `);
  });

  it.skip('indents and loosely wraps multi-line objects if needed', () => {
    check(`
      a: b
      c: d
    `, `
      ({
        a: b,
        c: d
      });
    `);
  });

  it.skip('adds curly braces loosely around a nested-object', () => {
    check(`
      a:
        b: c
    `, `
      ({
        a: {
          b: c
        }
      });
    `);
  });

  it.skip('uses concise methods for functions in objects', () => {
    check(`
      a: -> true
      b  :  -> false
    `, `
      ({
        a() { return true; },
        b() { return false; }
      });
    `);
  });
});

import check from './support/check';

describe('objects', () => {
  it('adds curly braces immediately around a single-line object', () => {
    check(`
      a b: c, d: e
    `, `
      a({b: c, d: e});
    `);
  });

  it.skip('indents and loosely wraps multi-line objects if needed', () => {
    check(`
      a: b
      c: d
    `, `
      ({
        a: b,
        c: d
      });
    `);
  });

  it.skip('adds curly braces loosely around a nested-object', () => {
    check(`
      a:
        b: c
    `, `
      ({
        a: {
          b: c
        }
      });
    `);
  });

  it.skip('uses concise methods for functions in objects', () => {
    check(`
      a: -> true
      b  :  -> false
    `, `
      ({
        a() { return true; },
        b() { return false; }
      });
    `);
  });

  it.skip('handles quoted strings as keys', () => {
    check(`
      write 301, '', 'Location': pathname+'/'
    `, `
      write(301, '', {'Location': pathname+'/'});
    `);
  });
});

Add a failing test for objects with quoted keys.


module.exports = {
    NotFound: require("./lib/NotFoundError.js"),
    Http: require("./lib/HttpError.js"),
    Custom: require("./lib/CustomError.js"),
    is: require("./lib/is.js"),
    Conflict: require("./lib/ConflictError.js"),
    InvalidArgument: require("./lib/InvalidArgumentError.js"),
    MissingArgument: require("./lib/MissingArgumentError.js"),
    Internal: require("./lib/InternalError.js")
};

module.exports = {
    NotFound: require("./lib/NotFoundError.js"),
    Http: require("./lib/HttpError.js"),
    Custom: require("./lib/CustomError.js"),
    is: require("./lib/is.js"),
    Conflict: require("./lib/ConflictError.js"),
    InvalidArgument: require("./lib/InvalidArgumentError.js"),
    MissingArgument: require("./lib/MissingArgumentError.js"),
    Unauthorized: require("./lib/UnauthorizedError.js"),
    Internal: require("./lib/InternalError.js")
};

Add the new error to interface


var es = require('event-stream'),
  beautify = require('node-beautify');

module.exports = function(opt){
  function modifyFile(file, cb){
    file.contents = beautify.beautifyJs(String(file.contents), opt);
    cb(null, file);
  }

  return es.map(modifyFile);
};

var es = require('event-stream'),
  beautify = require('node-beautify');

module.exports = function(opt){
  function modifyFile(file, cb){
    file.contents = new Buffer(beautify.beautifyJs(String(file.contents), opt));
    cb(null, file);
  }

  return es.map(modifyFile);
};

Return a Buffer rather than a string


window.VaadinComboBoxSuites = [
  'vaadin-combo-box.html',
  'toggling-dropdown.html',
  'overlay-position.html',
  'selecting-items.html',
  'form-input.html',
  'filtering.html',
  'keyboard.html',
  'scrolling.html',
  'aria.html',
  'using-object-values.html',
  'data-binding.html',
  'late-upgrade.html',
  'vaadin-combo-box-light.html',
  'item-template.html',
  'vaadin-combo-box-dropdown.html'
];

const isPolymer2 = document.querySelector('script[src*="wct-browser-legacy"]') === null;

window.VaadinComboBoxSuites = [
  'vaadin-combo-box.html',
  'toggling-dropdown.html',
  'overlay-position.html',
  'selecting-items.html',
  'form-input.html',
  'filtering.html',
  'keyboard.html',
  'scrolling.html',
  'aria.html',
  'using-object-values.html',
  'data-binding.html',
  'vaadin-combo-box-light.html',
  'item-template.html',
  'vaadin-combo-box-dropdown.html'
];

if (isPolymer2) {
  window.VaadinComboBoxSuites.push('late-upgrade.html');
}

Exclude tests usinig importHref from Polymer 3


// @flow

const RNI18n = require('react-native').NativeModules.RNI18n;
const I18nJs = require('i18n-js');

I18nJs.locale = RNI18n.languages[0];
export const getLanguages = RNI18n.getLanguages;
export default I18nJs;

// @flow

const RNI18n = require('react-native').NativeModules.RNI18n;
const I18nJs = require('i18n-js');

if (typeof RNI18n !== 'undefined') {
  I18nJs.locale = RNI18n.languages[0];
} else if (__DEV__) {
  console.warn('react-native-i18n module is not correctly linked');
}

export const getLanguages = RNI18n.getLanguages;
export default I18nJs;

Add a warning when the package is not linked


var session = null, picker;

// instead of windows.onload
$(document).ready( function() {
    // hide iphone/ipad URL bar
    setTimeout(function() { window.scrollTo(0, 1) }, 100);

    // initialize zoness
    session = new Session(
        SESSION_TYPE_DRAW,
        function() {
            //console.log("page_draw/ready: session callback ok");

            var board = new Board( session, 'session-board');
            var drawing = new Editor(session, board, 'session-drawing');
            var chat = new Chat(session);

            //console.log("page_draw/ready: prepicker");
            $("#brush").click(function(event){
                event.preventDefault();
                var firstClick = false;
                if (undefined === picker) {
                    picker = new Color.Picker({
                        size: Math.floor($(window).width() / 3),
                        callback: function(hex) {
                            drawing.color_set( "#" + hex );
                        }
                    });
                    picker.el.style.bottom = "50px";
                    picker.el.style.left = "10px";
                    firstClick = true;
                    $("#brush-action").text("Hide");
                }
                if (true === $(picker.el).is(":hidden")) {
                    $(picker.el).show();
                    $("#brush-action").text("Hide");
                } else if (!firstClick) {
                    $(picker.el).hide();
                    $("#brush-action").text("Show");
                }
            });
        }
    );
});

var session = null;

// instead of windows.onload
$(document).ready( function() {
    // hide iphone/ipad URL bar
    setTimeout(function() { window.scrollTo(0, 1) }, 100);

    // initialize zoness
    session = new Session(
        SESSION_TYPE_DRAW,
        function() {
            //console.log("page_draw/ready: session callback ok");

            var board = new Board( session, 'session-board');
            var drawing = new Editor(session, board, 'session-drawing');
            var chat = new Chat(session),
            picker = new Color.Picker({
                size: Math.floor($(window).width() / 3),
                callback: function(hex) {
                    drawing.color_set( "#" + hex );
                }
            });
            $(picker.el).hide(); // hide color picker on startup
            picker.el.style.bottom = "50px";
            picker.el.style.left = "10px";

            //console.log("page_draw/ready: prepicker");
            $("#brush").click(function(event){
                event.preventDefault();
                if (true === $(picker.el).is(":hidden")) {
                    $(picker.el).show();
                    $("#brush-action").text("Hide");
                } else {
                    $(picker.el).hide();
                    $("#brush-action").text("Show");
                }
            });
        }
    );
});

Initialize the color picker on startup but hide it, so the editor get the correct color.


require.config({
  baseUrl: 'js/lib',
  paths: {
    'test': '../../..',
    'mocha': 'mocha/mocha',
    'chai': 'chai/chai'
  },
  packages: [
    { name: 'md5', location: '../../../..', main: 'main' },
    { name: 'mocha-cloud', location: '../support', main: 'mocha-cloud' }
  ],
  shim: {
    'mocha': {
      exports: 'mocha'
    }
  }
});

require(['../suite']);

require.config({
  baseUrl: 'js/lib',
  paths: {
    'test': '../../..',
    'mocha': 'mocha/mocha',
    'chai': 'chai/chai'
  },
  packages: [
    { name: 'md5', location: '../../../..' },
    { name: 'mocha-cloud', location: '../support', main: 'mocha-cloud' }
  ],
  shim: {
    'mocha': {
      exports: 'mocha'
    }
  }
});

require(['../suite']);

Remove extraneous configuration in test setup.