var gulp = require("gulp");
var uglify = require("gulp-uglify");
var rename = require("gulp-rename");
var cleanCSS = require("gulp-clean-css");

var config = {};
config.srcPath = "./src/";
config.distPath = "./dist/";

config.cssSrcPath = config.srcPath + "css/*.css";
config.jsSrcPath = config.srcPath + "js/*.js";

config.cssDistPath = config.distPath + "css/";
config.jsDistPath = config.distPath + "js/";

// CSS Minification
gulp.task("css", () => {
  return gulp.src(config.cssSrcPath)
    .pipe(cleanCSS({compatibility: "ie8", level: {1: {specialComments: 0}} }))
    .pipe(rename({
    	suffix: ".min"
    }))
    .pipe(gulp.dest(config.cssDistPath));
});

// JS Minification
gulp.task("js", () => {
  return gulp.src(config.jsSrcPath)
    .pipe(uglify())
    .pipe(rename({
    	suffix: ".min"
    }))
    .pipe(gulp.dest(config.jsDistPath));
});

// gulp watch for css and js
gulp.task("watch", function() {
    gulp.watch(config.jsSrcPath, ["js"]);
    gulp.watch(config.cssSrcPath, ["css"]);
});

//gulp default
gulp.task("default",  ["css", "js"]);

var gulp = require("gulp");
var uglify = require("gulp-uglify");
var rename = require("gulp-rename");
var cleanCSS = require("gulp-clean-css");

var config = {};
config.srcPath = "./src/";
config.distPath = "./dist/";

config.cssSrcPath = config.srcPath + "css/*.css";
config.jsSrcPath = config.srcPath + "js/*.js";

config.cssDistPath = config.distPath + "css/";
config.jsDistPath = config.distPath + "js/";

// CSS Minification
gulp.task("css", () => {
  return gulp.src(config.cssSrcPath)
    .pipe(cleanCSS({compatibility: "ie8", level: {1: {specialComments: 0}} }))
    .pipe(rename({
    	suffix: ".min"
    }))
    .pipe(gulp.dest(config.cssDistPath));
});

// JS Minification
gulp.task("js", () => {
  return gulp.src(config.jsSrcPath)
    .pipe(uglify())
    .pipe(rename({
    	suffix: ".min"
    }))
    .pipe(gulp.dest(config.jsDistPath));
});

// gulp watch for css and js
gulp.task("watch", () => {
    gulp.watch(config.jsSrcPath, ["js"]);
    gulp.watch(config.cssSrcPath, ["css"]);
});

//gulp default
gulp.task("default",  ["css", "js"]);

Use short function like above

Standards:  Use short function like above


var OS = require("os");
var Config = require("truffle-config");
var Contracts = require("../contracts");
var Resolver = require("truffle-resolver");
var Artifactor = require("truffle-artifactor");
var Migrate = require("truffle-migrate");
var Environment = require("../environment");

var command = {
  command: 'migrate',
  description: 'Run migrations to deploy contracts',
  builder: {
    reset: {
      type: "boolean",
      default: false
    },
    "compile-all": {
      describe: "recompile all contracts",
      type: "boolean",
      default: false
    }
  },
  run: function (options, done) {
    var config = Config.detect(options);

    Contracts.compile(config, function(err) {
      if (err) return done(err);

      Environment.detect(config, function(err) {
        if (err) return done(err);

        config.logger.log("Using network '" + config.network + "'." + OS.EOL);

        Migrate.needsMigrating(config, function(err, needsMigrating) {
          if (err) return done(err);

          if (needsMigrating) {
            Migrate.run(config, done);
          } else {
            config.logger.log("Network up to date.")
            done();
          }
        });
      });
    });
  }
}

module.exports = command;

var OS = require("os");
var Config = require("truffle-config");
var Contracts = require("../contracts");
var Resolver = require("truffle-resolver");
var Artifactor = require("truffle-artifactor");
var Migrate = require("truffle-migrate");
var Environment = require("../environment");

var command = {
  command: 'migrate',
  description: 'Run migrations to deploy contracts',
  builder: {
    reset: {
      type: "boolean",
      default: false
    },
    "compile-all": {
      describe: "recompile all contracts",
      type: "boolean",
      default: false
    },
    f: {
      describe: "Specify a migration number to run from",
      type: "number"
    }
  },
  run: function (options, done) {
    var config = Config.detect(options);

    Contracts.compile(config, function(err) {
      if (err) return done(err);

      Environment.detect(config, function(err) {
        if (err) return done(err);

        config.logger.log("Using network '" + config.network + "'." + OS.EOL);

        if (options.f) {
          Migrate.runFrom(options.f, config, done);
        } else {
          Migrate.needsMigrating(config, function(err, needsMigrating) {
            if (err) return done(err);

            if (needsMigrating) {
              Migrate.run(config, done);
            } else {
              config.logger.log("Network up to date.")
              done();
            }
          });
        }
      });
    });
  }
}

module.exports = command;

Add the -f option to run from a specific migration.


"use strict"
var gulp = require("gulp");
var eslint = require("gulp-eslint");
var babel = require("gulp-babel");
var SOURCE_PATH = ["./src/**/*.js", "./src/**/*.jsx"];

gulp.task("build", function () {
  return gulp.src(SOURCE_PATH)
    .pipe(babel())
    .pipe(gulp.dest("lib"));
});
gulp.task("watch", function(callback) { gulp.watch(SOURCE_PATH, ["build"]) });

gulp.task("lint", function() {
  return gulp.src(SOURCE_PATH)
    .pipe(eslint())
    .pipe(eslint.format());
});

gulp.task("default", ["build", "watch"]);

"use strict"
var gulp = require("gulp");
var eslint = require("gulp-eslint");
var babel = require("gulp-babel");
var SOURCE_PATH = ["./src/**/*.js", "./src/**/*.jsx"];

// gulp.task("build", function () {
//   return gulp.src(SOURCE_PATH)
//     .pipe(babel())
//     .pipe(gulp.dest("lib"));
// });
// gulp.task("watch", function(callback) { gulp.watch(SOURCE_PATH, ["build"]) });

gulp.task("lint", function() {
  return gulp.src(SOURCE_PATH)
    .pipe(eslint())
    .pipe(eslint.format());
});

gulp.task("default", ["lint"]);

Comment out build step (gulp).

Comment out build step (gulp).


"use strict";
var gulp   = require('gulp'),
	jshint = require('gulp-jshint'),
	filter = require('gulp-filter'),
	mocha  = require('gulp-mocha');

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

gulp.task('watch', function () {
	gulp.watch('test/*.js', ['test']);
});

gulp.task('test', ['lint'], function () {
	gulp.src('test/*.js', {read: false})
		.pipe(mocha({reporter: 'spec', ui: 'bdd'}));
});

gulp.task('lint', function () {
	return gulp.src('**/*.js')
		.pipe(filter(['*', '!node_modules/**/*']))
		.pipe(jshint({node: true}))
		.pipe(jshint.reporter('default'));
});

"use strict";
var gulp   = require('gulp'),
	jshint = require('gulp-jshint'),
	filter = require('gulp-filter'),
	mocha  = require('gulp-mocha');

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

gulp.task('watch', function () {
	gulp.watch(['**/*.js', '!node_modules/**/*.js'], ['test']);
});

gulp.task('test', ['lint'], function () {
	gulp.src('test/*.js', {read: false})
		.pipe(mocha({reporter: 'spec', ui: 'bdd'}));
});

gulp.task('lint', function () {
	return gulp.src('**/*.js')
		.pipe(filter(['*', '!node_modules/**/*']))
		.pipe(jshint({node: true}))
		.pipe(jshint.reporter('default'));
});

Add all .js files to gulp.watch instead of just the files under 'test/'


// Module dependencies.
var debug = require('debug')('ruche:error');

/**
 * Handle errors
 * @param  {Error} error
 * @return {Error}
 */
var handle = function (err) {
  debug(err);
  process.exit(1)
  return err;
};

var exception = function () {
  process.on('uncaughtException', function (err) {
    handle(err);
  });
}

module.exports.handle = handle;
module.exports.exception = exception;

// Module dependencies.
var debug = require('debug')('ruche:error');

/**
 * Handle errors
 * @param  {Error} error
 * @return {Error}
 */
var handle = function (err) {
  debug(err);
  process.exit(1)
  return err;
};

/**
 * The uncaughtException handler. Stops the process on Error
 * @return {Boolean} Returns the status of the app.
 */
var exception = function () {
  process.on('uncaughtException', function (err) {
    handle(err);
    return false;
  });
  return true;
}

module.exports.handle = handle;
module.exports.exception = exception;

Add documentation to uncaughtException handler.


'use strict';

import Login from '../src/Login';

describe('Login', function() {
	it('should be tested', function() {
		assert.fail('No tests for this module yet.');
	});
});

'use strict';

import Login from '../src/Login';

describe('Login', function() {

	beforeEach(function () {
		this.xhr = sinon.useFakeXMLHttpRequest();
		var requests = this.requests = [];
		this.xhr.onCreate = function (xhr) {
			requests.push(xhr);
		};
	});

	afterEach(function () {
		this.xhr.restore();
	});

	it('should add a component to the DOM', function() {
		// assert.fail('No tests for this module yet.');

		let login = new Login();
		let el = document.querySelector('.loginmodal-container');
		assert.ok(el);
	});

	it('should try to login and emit an error event if it fails', function(done) {
		let callback = sinon.spy();
		let login = new Login();

		login.on('loginError', function () {
			callback();
			assert.deepEqual(callback.called, true);
			done();
		});

		let btn = login.element.querySelector('input[type="submit"]');
		btn.click();
	});

	it('should try to login and emit a success event if it works', function(done) {
		let callback = sinon.spy();

		let login = new Login();
		login.userEl.value = 'test';
		login.passEl.value = 'test';

		login.on('loginSuccess', function (val) {
			callback();
			assert.deepEqual(callback.called, true);
			assert.deepEqual(val.status, 200);
			done();
		});

		let btn = login.element.querySelector('input[type="submit"]');
		btn.click();
		this.requests[0].respond(200);
	});
});

Add test for login component

Add test for login component


//
// Copyright 2012 Shared Learning Collaborative, LLC
//
// 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.
//

db["error"].ensureIndex({"batchJobId":1, "resourceId":1});
db["newBatchJob"].ensureIndex({"jobStartTimestamp":1}); // only for job reporting tool
db["batchJobStage"].ensureIndex({"jobId":1, "stageName":1});
db["transformationLatch"].ensureIndex({"jobId" : 1, "syncStage" : 1, "recordType" : 1}, {unique : true});
db["persistenceLatch"].ensureIndex({"jobId" : 1, "syncStage" : 1, "entities" : 1}, {unique : true});
db["stagedEntities"].ensureIndex({"jobId" : 1}, {unique : true});
db["recordHash"].ensureIndex({"tenantId":1});

Revert "DE2347 - Remove tenantId index from recordHash as intended"

This reverts commit 6718f6f8388ca42d85c6403129be29d2c36852e8.

Need to keep the index because purging the data in recordHash,
which remains shared across tenants in ingestion_batch_job,
requires a full-table-table scan when the index is absent.
That in turn breaks in CI which prohibits full table scans.


var gulp = require('gulp');
var ts = require('gulp-typescript');
var tslint = require('gulp-tslint');
var jade = require('gulp-jade');

gulp.task('jade', function() {
    gulp.src('./src/views/*.jade')
        .pipe(jade())
        .pipe(gulp.dest('./dist/'))
});

gulp.task('typescript', function() {
    gulp.src('src/scripts/**/*.ts')
        .pipe(tslint())
        .pipe(tslint.report('verbose'))
        .pipe(ts({
            declarationFiles: true,
            target: 'es5'
        }));
});

gulp.task('default', function () {
});

var gulp = require('gulp');
var ts = require('gulp-typescript');
var tslint = require('gulp-tslint');
var jade = require('gulp-jade');

gulp.task('jade', function() {
    gulp.src('./src/views/*.jade')
        .pipe(jade())
        .pipe(gulp.dest('./dist/'))
});

gulp.task('typescript', function() {
    gulp.src('src/scripts/**/*.ts')
        .pipe(tslint())
        .pipe(tslint.report('verbose'))
        .pipe(ts({
            declarationFiles: true,
            target: 'es5'
        })
        .pipe(gulp.dest('./dist/scripts/')));
});

gulp.task('default', function () {
});

Set JavaScript file destination directory, after TypeScript compile


$(document).ready(function() {

  $(".welcome").on("click", function() {
    console.log("YES");
    $(this).slideUp(1500);
    // $(this).parent().slideUp(1500);
    $(this).parent().animate({ height: 'toggle', opacity: 0.5 }, 1500);
  });

  $("#about").on("click", function() {
    var popupBox = $(".popup-about");
    popupBox.fadeIn(400);
    $('body').append('

');
    $("#mask").fadeIn(400);
  });

  $("#start").on("click", function() {
    var popupBox = $(".popup-start");
    popupBox.fadeIn(400);
    $('body').append('

');
    $("#mask").fadeIn(400);
  });

  $("#meet").on("click", function() {
    var popupBox = $(".popup-meet");
    popupBox.fadeIn(400);
    $('body').append('

');
    $("#mask").fadeIn(400);
  });

});

$(document).ready(function() {

  $(".welcome").on("click", function() {
    console.log("YES");
    $(this).fadeOut(1400);
    $(this).parent().slideUp(1800);
    // $(this).slideUp(1200);
    // $(this).parent().animate({ height: 'toggle', opacity: 0.5 }, 1500);
  });

  $("#about").on("click", function() {
    var popupBox = $(".popup-about");
    popupBox.fadeIn(400);
    $('body').append('

');
    $("#mask").fadeIn(400);
  });

  $("#start").on("click", function() {
    var popupBox = $(".popup-start");
    popupBox.fadeIn(400);
    $('body').append('

');
    $("#mask").fadeIn(400);
  });

  $("#meet").on("click", function() {
    var popupBox = $(".popup-meet");
    popupBox.fadeIn(400);
    $('body').append('

');
    $("#mask").fadeIn(400);
  });

});

Modify slide and fade features

Modify slide and fade features


var gulp = require('gulp');
var mocha = require('gulp-mocha');
var istanbul = require('gulp-istanbul');
var eslint = require('gulp-eslint');
var coveralls = require('gulp-coveralls');

gulp.task('pre-test', function () {
  return gulp.src(['lib/**/*.js', '!lib/micro-whalla.js'])
    .pipe(istanbul({ includeUntested: true }))
    .pipe(istanbul.hookRequire());
});

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

gulp.task('lint', function () {
  return gulp.src(['**/*.js', '!node_modules/**', '!coverage/**'])
    .pipe(eslint())
    .pipe(eslint.format())
    .pipe(eslint.failAfterError());
});

gulp.task('coveralls', function () {
  return gulp.src('coverage/**/lcov.info')
    .pipe(coveralls());
});

gulp.task('default', ['test'], function () {

});

var gulp = require('gulp');
var mocha = require('gulp-mocha');
var istanbul = require('gulp-istanbul');
var eslint = require('gulp-eslint');
var coveralls = require('gulp-coveralls');

gulp.task('pre-test', function () {
  return gulp.src(['lib/**/*.js', '!lib/micro-whalla.js', '!lib/helpers.js'])
    .pipe(istanbul({ includeUntested: true }))
    .pipe(istanbul.hookRequire());
});

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

gulp.task('lint', function () {
  return gulp.src(['**/*.js', '!node_modules/**', '!coverage/**'])
    .pipe(eslint())
    .pipe(eslint.format())
    .pipe(eslint.failAfterError());
});

gulp.task('coveralls', function () {
  return gulp.src('coverage/**/lcov.info')
    .pipe(coveralls());
});

gulp.task('default', ['test'], function () {

});

Add helpers.js to ignore from tests

Add helpers.js to ignore from tests


'use strict'

const log = require('./log.js')
const mm = require('micromatch')
const chalk = require('chalk')
const watcher = require('simple-watcher')

class Watcher {
  watch ({workingDir, exclude, callback}) {
    log.info(`Scanning: ${chalk.yellow(workingDir)} ...`)

    watcher(workingDir, (localPath) => {
      log.debug('Changed:', localPath)

      // Skip excluded.
      if (exclude && mm([localPath], {dot: true}, exclude).length > 0) {
        return
      }

      callback(localPath)
    }, 0)

    log.info('Awaiting changes ...')
  }
}

module.exports = Watcher

'use strict'

const log = require('./log.js')
const mm = require('micromatch')
const chalk = require('chalk')
const watcher = require('simple-watcher')

class Watcher {
  watch ({workingDir, exclude, callback}) {
    log.info(`Scanning: ${chalk.yellow(workingDir)} ...`)

    watcher(workingDir, (localPath) => {
      log.debug('Changed:', localPath)

      // Skip excluded.
      if (exclude && mm([localPath], exclude, {dot: true}).length > 0) {
        return
      }

      callback(localPath)
    }, 0)

    log.info('Awaiting changes ...')
  }
}

module.exports = Watcher

Fix order of micromatch parameters

Fix order of micromatch parameters


// Generated by CoffeeScript 1.6.2
(function() {
  var coffee, concat, gulp, gutil, mocha, uglify, wrap;

  gulp = require('gulp');

  coffee = require('gulp-coffee');

  concat = require('gulp-concat');

  gutil = require('gulp-util');

  mocha = require('gulp-mocha');

  uglify = require('gulp-uglify');

  wrap = require('gulp-wrap-umd');

  gulp.task('caffeinate', function() {
    gulp.src('src/*.coffee').pipe(coffee({
      bare: true
    })).on('error', gutil.log).pipe(gulp.dest('./tmp/build'));
    return gulp.src('test/*.coffee').pipe(coffee()).on('error', gutil.log).pipe(gulp.dest('./tmp'));
  });

  gulp.task('build', ['caffeinate'], function() {
    return gulp.src(['lib/*.js', 'tmp/build/*.js']).pipe(concat('main.js')).pipe(wrap({
      exports: 'exposed'
    })).pipe(uglify()).pipe(gulp.dest('./dist/'));
  });

  gulp.task('test', ['build'], function() {
    return gulp.src('tmp/*.js').pipe(mocha());
  });

  gulp.task('default', function() {
    gulp.run('build');
    return gulp.watch(['lib/base64-binary.js', 'src/validate-ssh.coffee'], function(event) {
      return gulp.run('build');
    });
  });

}).call(this);

//the build instructions are in gulpfile.coffee
//this file is a simple bridge since gulp doesn't support
//coffeescript files natively.

require('coffee-script');
require('./gulpfile.coffee');

Use bridge gulp file instead of having to re-generate.


var elixir = require('laravel-elixir');

/*
 |--------------------------------------------------------------------------
 | Elixir Asset Management
 |--------------------------------------------------------------------------
 |
 | Elixir provides a clean, fluent API for defining some basic Gulp tasks
 | for your Laravel application. By default, we are compiling the Less
 | file for our application, as well as publishing vendor resources.
 |
 */

elixir(function(mix) {
    mix.sass('app.scss');
});

var elixir = require('laravel-elixir');

/*
 |--------------------------------------------------------------------------
 | Elixir Asset Management
 |--------------------------------------------------------------------------
 |
 | Elixir provides a clean, fluent API for defining some basic Gulp tasks
 | for your Laravel application. By default, we are compiling the Sass
 | file for our application, as well as publishing vendor resources.
 |
 */

elixir(function(mix) {
    mix.sass('app.scss');
});

Change comment to reflect the change of the default css preprocessor.


import Command from './Command.js';

/**
 * Table Command
 */
export default class TableCommand extends Command {
    /**
     * @inheritDoc
     */
    execute() {
        const figure = this.editor.document.createElement('figure');
        const table = this.editor.document.createElement('table');
        const figcaption = this.editor.document.createElement('figcaption');

        figure.classList.add('table');
        figure.appendChild(table);
        figure.appendChild(figcaption);

        ['thead', 'tbody', 'tfoot'].forEach(part => {
            const item = this.editor.document.createElement(part);
            const tr = this.editor.document.createElement('tr');
            table.appendChild(item);
            item.appendChild(tr);

            for (let i = 0; i < 2; ++i) {
                let cell = this.editor.document.createElement(part === 'thead' ? 'th' : 'td');
                tr.appendChild(cell);
            }
        });

        this.editor.insert(figure);
    }
}

import Command from './Command.js';

/**
 * Table Command
 */
export default class TableCommand extends Command {
    /**
     * @inheritDoc
     */
    execute() {
        const figure = this.editor.document.createElement('figure');
        const table = this.editor.document.createElement('table');
        const figcaption = this.editor.document.createElement('figcaption');

        figure.classList.add('table');
        figure.appendChild(table);
        figure.appendChild(figcaption);

        ['thead', 'tbody', 'tfoot'].forEach(section => {
            const item = this.editor.document.createElement(section);
            const tr = this.editor.document.createElement('tr');
            table.appendChild(item);
            item.appendChild(tr);

            for (let i = 0; i < 2; ++i) {
                let cell = this.editor.document.createElement(section === 'thead' ? 'th' : 'td');
                tr.appendChild(cell);
            }
        });

        this.editor.insert(figure);
    }
}

Rename param to be consistent

Rename param to be consistent


'use strict';

// @ngInject
var authorsDirective = function() {
  return {
    scope: {
      authors: '='
    },
    template: require('./authorstemplate.html'),
    //@ngInject
    controller: function($scope) {
      $scope.fullnames = function (authors) {
        return authors.reduce((m, a, i) => m + a.first_name + ' ' + a.last_name + (i < authors.length-1 ? ', ':''), '');
      };
    }
  };
};

module.exports = authorsDirective;

'use strict';

// @ngInject
var authorsDirective = function() {
  return {
    scope: {
      authors: '='
    },
    template: require('./authorstemplate.html'),
    //@ngInject
    controller: function($scope) {
      $scope.fullnames = function (authors) {
        return authors.reduce((m, a, i) => {
          return m +
            (a.first_name ? a.first_name + ' ' + a.last_name : a.name) +
            (i < authors.length-1 ? ', ':'');
        }, '');
      };
    }
  };
};

module.exports = authorsDirective;

Support first_name, last_name and name

Support first_name, last_name and name


var Minionette = (function(global, _, $, Backbone) {
    'use strict';

    // Define and export the Minionette namespace
    var Minionette = {};
    Backbone.Minionette = Minionette;

    // @include ../jquery.cleanData.js

    // @include ../view.js
    // @include ../region.js
    // @include ../model_view.js
    // @include ../collection_view.js

    return Minionette;
})(this, _, jQuery, Backbone);

var Minionette = (function(global, _, $, Backbone) {
    'use strict';

    // Define and export the Minionette namespace
    var Minionette = {};
    Backbone.Minionette = Minionette;

    // @include ../jquery.cleanData.js

    // @include ../region.js
    // @include ../view.js
    // @include ../model_view.js
    // @include ../collection_view.js

    return Minionette;
})(this, _, jQuery, Backbone);

Make sure Region is included before View

View depends on Region


var gulp  = require('gulp')
var shell = require('./')

var paths = {
  js: ['*.js', 'test/*.js']
}

gulp.task('test', shell.task('mocha -R spec -r should'))

gulp.task('coverage', ['test'], shell.task('istanbul cover _mocha -- -R spec'))

gulp.task('coveralls', ['coverage'], shell.task('cat coverage/lcov.info | coveralls'))

gulp.task('lint', shell.task([
  'jshint ' + paths.js.join(' '),
  'jscs '   + paths.js.join(' '),
]))

gulp.task('default', ['coverage', 'lint'])

gulp.task('watch', function () {
  // Keep watch running on errors.
  gulp.on('err', function () {})

  gulp.watch(paths.js, ['default'])
})

var gulp  = require('gulp')
var shell = require('./')

var paths = {
  js: ['*.js', 'test/*.js']
}

gulp.task('test', shell.task('mocha -R spec -r should'))

gulp.task('coverage', ['test'], shell.task('istanbul cover _mocha -- -R spec'))

gulp.task('coveralls', ['coverage'], shell.task('cat coverage/lcov.info | coveralls'))

gulp.task('lint', shell.task([
  'jshint ' + paths.js.join(' '),
  'jscs '   + paths.js.join(' '),
]))

gulp.task('default', ['coverage', 'lint'])

gulp.task('watch', function () {
  gulp.watch(paths.js, ['default'])
})

Remove dirty hack for keeping watch running on errors


/**
 * @file Etherscan API client.
 * @module client/etherscan
 */

'use strict'

/**
 * Etherscan API client.
 * @static
 */
class Client {

}

// Expose
module.exports = Client

/**
 * @file Etherscan API client.
 * @module client/etherscan
 */

'use strict'

/**
 * Private members store.
 * @private
 */
const privs = new WeakMap()

/**
 * Etherscan API client.
 * @static
 */
class Client {
  /**
   * No parameters.
   */
  constructor () {
    const priv = {}
    privs.set(this, priv)
  }
}

// Expose
module.exports = Client

Add private members store to Etherscan client


var gulp = require('gulp');
var $ = require('gulp-load-plugins')({
  camelize: true
});

var config = {
  source: {
    scripts: {
      path: 'app/',
      files: './app/**/*.js'
    }
  },
  build: {
    scripts: 'build/scrips/'
  }
}

gulp.task('build-scripts', function() {
  return gulp.src(config.source.scripts.files)
    .pipe($.concat('app-build.js'))
    .pipe($.uglify({mangle: false }))
    .pipe(gulp.dest(config.build.scripts));

});

gulp.task('default', function() {
  // place code for your default task here
});

var gulp = require('gulp');
var $ = require('gulp-load-plugins')({
  camelize: true
});

var config = {
  source: {
    scripts: {
      path: 'app/',
      files: './app/**/*.js'
    },
    markup: {
      path: 'app/',
      files: './app/**/*.html'
    }
  },
  build: {
    scripts: 'build/scrips/',
    markup: 'build/'
  }
}

gulp.task('build-scripts', function() {
  return gulp.src(config.source.scripts.files)
    .pipe($.concat('app-build.js'))
    .pipe($.uglify({mangle: false }))
    .pipe(gulp.dest(config.build.scripts));
});

gulp.task('build-markup', function() {
  return gulp.src(config.source.markup.files)
    .pipe(gulp.dest(config.build.markup));
});

gulp.task('default', function() {
  // place code for your default task here
});

Add gulp task build markup

Add gulp task build markup


var gulp = require('gulp')
var sass = require('gulp-sass')
var browserSync = require('browser-sync').create()

gulp.task('sass', function () {
  return gulp.src('./scss/**/*.scss')
    .pipe(sass().on('error', sass.logError))
    .pipe(gulp.dest('./css'))
})

gulp.task('browser-sync', function() {
  browserSync.init({
    server: {
      baseDir: './'
    }
  })
})

gulp.task('default', ['sass', 'browser-sync'], function() {
  gulp.watch('./sass/**/*.scss', ['sass'])
})

var gulp = require('gulp')
var sass = require('gulp-sass')
var browserSync = require('browser-sync').create()

gulp.task('sass', function () {
  return gulp.src('./scss/**/*.scss')
    .pipe(sass())
    .pipe(gulp.dest('./css'))
    .pipe(browserSync.stream())
})

gulp.task('browser-sync', function() {
  browserSync.init({
    server: {
      baseDir: './'
    }
  })

  gulp.watch('./**/*.scss', ['sass'])
  gulp.watch('./index.html').on('change', browserSync.reload)
})

gulp.task('default', ['browser-sync'], function() {
  gulp.watch('./sass/**/*.scss', ['sass'])
})

Fix gulfile not watching Sass changes

Fix gulfile not watching Sass changes


import StoriesItemType from '../types/StoriesItemType'
import RankingInputItemType from '../types/RankingInputItemType'
import {Story, User, Ranking} from '../models'

const addRanking = {
  name: 'addRanking',
  type: StoriesItemType,
  args: {
    story: {type: RankingInputItemType}
  },
  async resolve (value, {story}) {
    let userId = value.request.user.id
    let storyId = story.id
    let ranking = await Ranking.findOne({where: {userId, storyId}})
    if (! ranking){
      Ranking.create({userId, storyId})
    }
    let result = await Story.findById(storyId, {
      include: [{
        model: User,
        as: 'user'
      },{
        model: Ranking,
        as: 'rankings'
      }]
    })
    return result
  }
}

export default addRanking

import StoriesItemType from '../types/StoriesItemType'
import RankingInputItemType from '../types/RankingInputItemType'
import {Story, User, Ranking} from '../models'

const addRanking = {
  name: 'addRanking',
  type: StoriesItemType,
  args: {
    story: {type: RankingInputItemType}
  },
  async resolve (value, {story}) {
    let userId = value.request.user.id
    let storyId = story.id
    let user = await User.findById(userId)
    if (user){
      let ranking = await Ranking.findOne({where: {userId, storyId}})
      if (! ranking){
        Ranking.create({userId, storyId})
      }
      let result = await Story.findById(storyId, {
        include: [{
          model: User,
          as: 'user'
        },{
          model: Ranking,
          as: 'rankings'
        }]
      })
      return result
    }else{
      throw 'Invalid user!'
    }
  }
}

export default addRanking

Add user check to add ranking

Add user check to add ranking


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

/*
 * Hide the password. Uses the password to form authorization strings,
 * but provides no interface for exporting it.
 */
function user_credentials(username,password) {
  if (username.is_user_credentials &&
    typeof username.basic === 'function' &&
    typeof username.digest === 'function'
  ) {
    return username;
  }

  var basic_string= !password && password !== '' ?
    new Buffer(username, "ascii").toString("base64")
  :
    new Buffer(username+':'+password, "ascii").toString("base64")
  ;
  function basic()
  {
    return basic_string;
  }
  function digest(realm) {
    return !password && password !== '' ?
        md5(username+':'+realm)
        :
        md5(username+':'+realm+':'+password)
  }
  return {
    basic: basic,   // basic() returns a hash of username:password
    digest: digest, // digest(realm) returns a u & p hash for that realm
    username: username,
    is_user_credentials: true
  }
}

module.exports= user_credentials;

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

/*
 * Hide the password. Uses the password to form authorization strings,
 * but provides no interface for exporting it.
 */
function user_credentials(username,password) {
  if (username.is_user_credentials &&
    typeof username.basic === 'function' &&
    typeof username.digest === 'function'
  ) {
    return username;
  }

  var basic_string= !password && password !== '' ?
    new Buffer(username, "ascii").toString("base64")
  :
    new Buffer(username+':'+password, "ascii").toString("base64")
  ;

  function Credentials()
  {
    this.username= username;
  }
  Credentials.prototype.basic= function()
  {
    return basic_string;
  }
  Credentials.prototype.digest= function(realm)
  {
    return !password && password !== '' ?
        md5(username+':'+realm)
        :
        md5(username+':'+realm+':'+password)
  }
  Credentials.prototype.is_user_credentials= function()
  {
    return true;
  }

  return new Credentials;
}

module.exports= user_credentials;

Refactor user credentials as a prototyped object.


var gulp = require('gulp');
var nodemon = require('nodemon');
var webpack = require('webpack');
var clientConfig = require('./webpack.config');
var path = require('path');

function onBuild(cb) {
  return function(err, stats) {
    if (err)
      console.log('Error', err);
    else
      console.log(stats.toString());

    if (cb) cb();
  }
}

// Serverside (backend) tasks group
// Nothing so far!

// Clientside (frontend) tasks
gulp.task('client-watch', function() {
  // Changes within 100 ms = one rebuild
  webpack(clientConfig).watch(100, onBuild);
});

gulp.task('client-build', function(cb) {
  webpack(clientConfig).run(onBuild(cb));
});

// Group tasks

// For development - rebuilds whenever something changes
gulp.task('watch', ['client-watch']);

// For production - builds everything
gulp.task('build', ['client-build']);

// Nodemon is used. Maybe it's better to use gulp's own watch system?
gulp.task('run', ['client-watch'], function() {
  nodemon({
    execMap: {
      js: 'node'
    },
    script: path.join(__dirname, 'server/main.js'),
    ext: 'js json'
  }).on('restart', function() {
    console.log('Restarted!');
  });
});

var gulp = require('gulp');
var nodemon = require('nodemon');
var webpack = require('webpack');
var clientConfig = require('./webpack.config');
var path = require('path');

var wpCompiler = webpack(clientConfig);

function onBuild(cb) {
  return function(err, stats) {
    if (err)
      console.log('Error', err);
    else
      console.log(stats.toString());

    if (cb) cb();
  }
}

// Serverside (backend) tasks group
// Nothing so far!

// Clientside (frontend) tasks
gulp.task('client-watch', function() {
  // Changes within 100 ms = one rebuild
  wpCompiler.watch({
      aggregateTimeout: 100
    },
    onBuild());
});

gulp.task('client-build', function(cb) {
  wpCompiler.run(onBuild(cb));
});

// Group tasks

// For development - rebuilds whenever something changes
gulp.task('watch', ['client-watch']);

// For production - builds everything
gulp.task('build', ['client-build']);

// Nodemon is used. Maybe it's better to use gulp's own watch system?
gulp.task('run', ['client-watch'], function() {
  nodemon({
    execMap: {
      js: 'node'
    },
    script: path.join(__dirname, 'server/main.js'),
    ext: 'js json'
  }).on('restart', function() {
    console.log('Restarted!');
  });
});

Fix onBuild callback for webpack watch mode, now it properly outputs what it should to the log (screen). Also microrefactor the webpack calling code.


/*
Copyright 2014 Spotify AB

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.
*/

/* global require */

var gulp = require('gulp');
var qunit = require('gulp-qunit');
var jshint = require('gulp-jshint');
var htmlhint = require("gulp-htmlhint");
var csslint = require("gulp-csslint");

gulp.task('test', function() {
    return gulp.src('./test.html').pipe(qunit());
});

gulp.task('jslint', function() {
    return gulp.src('*.js')
        .pipe(jshint())
        .pipe(jshint.reporter('default'))
        .pipe(jshint.reporter('fail'));
});

gulp.task('htmllint', function() {
    return gulp.src(["*.html", "!test.html"])
        .pipe(htmlhint())
        .pipe(htmlhint.reporter())
        .pipe(htmlhint.failReporter());
});

gulp.task('csslint', function() {
    gulp.src('*.css')
        .pipe(csslint())
        .pipe(csslint.reporter())
        .pipe(csslint.failReporter());
});

/*
Copyright 2014 Spotify AB

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.
*/

/* global require */

var gulp = require('gulp');
var qunit = require('gulp-qunit');
var jshint = require('gulp-jshint');
var htmlhint = require("gulp-htmlhint");
var csslint = require("gulp-csslint");

gulp.task('test', function() {
    return gulp.src('file://test.html').pipe(qunit());
});

gulp.task('jslint', function() {
    return gulp.src('*.js')
        .pipe(jshint())
        .pipe(jshint.reporter('default'))
        .pipe(jshint.reporter('fail'));
});

gulp.task('htmllint', function() {
    return gulp.src(["*.html", "!test.html"])
        .pipe(htmlhint())
        .pipe(htmlhint.reporter())
        .pipe(htmlhint.failReporter());
});

gulp.task('csslint', function() {
    gulp.src('*.css')
        .pipe(csslint())
        .pipe(csslint.reporter())
        .pipe(csslint.failReporter());
});

Fix headless unit test running

Fix headless unit test running

Now "npm install && npm test" works locally again.


const fs = require("fs");
const path = require("path");
const { src, dest, task, watch, series } = require('gulp');
const Gitdown = require('@gnd/gitdown');
const rename = require("gulp-rename");
const debug = require("gulp-debug");
const pandoc = require("gulp-pandoc");

task('gitdown', async () => {
  if (!fs.existsSync("dist")) {
    fs.mkdirSync("dist");
  }

  const gitdown = Gitdown.readFile(path.join(__dirname, "src", "index.md"));

  gitdown.registerHelper("scroll-up", {
    compile: (config) => {
      return "<sup>[ [^](#user-content-contents) _Back to contents_ ]</sup>";
    }
  });

  await gitdown.writeFile('dist/_merged.md');
});

task('pandoc', () => {
  return src("dist/_merged.md")
    .pipe(debug({ title: "merged" }))
    .pipe(pandoc({
      from: "gfm",
      to: "gfm",
      args: ['--wrap=none'],
      ext: "md"
    }))
    .pipe(debug({ title: "pandoc output:" }))
    .pipe(rename("output.md"))
    .pipe(dest("dist"));
});

task('build', series("gitdown", "pandoc"));

task('watch', series(["build", () => {
  watch('./src', series(['build']));
}]));

task('default', series('build'));

const fs = require("fs");
const path = require("path");
const { src, dest, task, watch, series } = require('gulp');
const Gitdown = require('@gnd/gitdown');
const rename = require("gulp-rename");
const debug = require("gulp-debug");
const pandoc = require("gulp-pandoc");

task('gitdown', async () => {
  if (!fs.existsSync("dist")) {
    fs.mkdirSync("dist");
  }

  const gitdown = Gitdown.readFile(path.join(__dirname, "src", "index.md"));

  gitdown.registerHelper("scroll-up", {
    compile: (config) => {
      if (config.downRef) {
        return `<sup>[ [∧](#user-content-contents) _Back to contents_ | _${config.downTitle}_ [∨](${config.downRef}) ]</sup>`;
      } else {
        return "<sup>[ [∧](#user-content-contents) _Back to contents_ ]</sup>";
      }
    }
  });

  await gitdown.writeFile('dist/_merged.md');
});

task('pandoc', () => {
  return src("dist/_merged.md")
    .pipe(debug({ title: "merged" }))
    .pipe(pandoc({
      from: "gfm",
      to: "gfm",
      args: ['--wrap=none'],
      ext: "md"
    }))
    .pipe(debug({ title: "pandoc output:" }))
    .pipe(rename("output.md"))
    .pipe(dest("dist"));
});

task('build', series("gitdown", "pandoc"));

task('watch', series(["build", () => {
  watch('./src', series(['build']));
}]));

task('default', series('build'));

Make scroll-up thingy support scroll-down thingy


var gulp = require("gulp");
var sass = require("gulp-sass");

gulp.task('sass', function () {
    gulp.src('src/hipster-grid-system.scss')
        .pipe(sass())
        .pipe(gulp.dest('dist'));
});

var gulp = require("gulp");
var sass = require("gulp-sass");
var rename = require("gulp-rename");
var autoprefixer = require("gulp-autoprefixer");

gulp.task('sass', function () {
    gulp.src('src/hipster-grid-system.scss')
        .pipe(sass())
        .pipe(autoprefixer())
        .pipe(gulp.dest('dist'));
    gulp.src('src/hipster-grid-system.scss')
        .pipe(sass({outputStyle: 'compressed'}))
        .pipe(autoprefixer())
        .pipe(rename({
            suffix: ".min"
        }))
        .pipe(gulp.dest('dist'));
});

Add support autoprefixer for cross-browser. Add support minify dist file.


'use strict';

// DEV TIME CODE
if (FAKE_SERVER) {
    require('fake');
}
// DEV TIME CODE

require('./index.scss');

var $ = require('$jquery');
var util = require('lib/util');
var state = require('./state');
var repository = require('./repository');
var sections = require('./sections/section');

//var details = args.newData.hud;
var setup = state.current();

// only load things when we have the data ready to go
repository.getData(function(details) {
	// generate the html needed for the sections
	var html = sections.render(details, setup);
	html = '

' + html + '

';

	// insert the html into the dom
	var holder = $(html).appendTo('body')

	// force the correct state from previous load
	state.setup(holder);

	// setup events that we need to listen to
	sections.postRender(holder);

	// TODO: need to find a better place for this
	$('.glimpse-icon').click(function() {
		window.open(util.resolveClientUrl(util.currentRequestId(), true), 'GlimpseClient');
	});
});

'use strict';

// DEV TIME CODE
if (FAKE_SERVER) {
    require('fake');
}
// DEV TIME CODE

require('./index.scss');

var $ = require('$jquery');
var util = require('lib/util');
var state = require('./state');
var repository = require('./repository');
var sections = require('./sections/section');

//var details = args.newData.hud;
var setup = state.current();

// only load things when we have the data ready to go
repository.getData(function(details) {
	$(function() { setTimeout(function() {
		// generate the html needed for the sections
		var html = sections.render(details, setup);
		html = '

' + html + '

';

		// insert the html into the dom
		var holder = $(html).appendTo('body')

		// force the correct state from previous load
		state.setup(holder);

		// setup events that we need to listen to
		sections.postRender(holder);

		// TODO: need to find a better place for this
		$('.glimpse-icon').click(function() {
			window.open(util.resolveClientUrl(util.currentRequestId(), true), 'GlimpseClient');
		});
	}, 0); });
});

Fix bug where Navigation Timing info could be accessed to quickly and hence produce weird values


const Redis = require('ioredis');

module.exports = url => {
  const redis = new Redis(url);

  redis.setJSON = async (...arguments) => {
    arguments[1] = JSON.stringify(arguments[1]);
    if (typeof arguments[2] === 'object' && arguments[2].asSeconds) {
      arguments[2] = parseInt(arguments[2].asSeconds());
    }
    if (typeof arguments[2] === 'number') {
      arguments[3] = parseInt(arguments[2]);
      arguments[2] = 'EX';
    }
    return await redis.set.apply(redis, arguments);
  }

  redis.getJSON = async key => {
    const value = await redis.get(key);
    if (value) {
      return JSON.parse(value);
    }
    return value;
  }

  return redis;
};

const Redis = require('ioredis');

module.exports = url => {
  const redis = new Redis(url);

  redis.setJSON = async (...arguments) => {
    arguments[1] = JSON.stringify(arguments[1]);
    if (typeof arguments[2] === 'object' && arguments[2].asSeconds) {
      arguments[2] = parseInt(arguments[2].asSeconds());
    }
    if (typeof arguments[2] === 'number') {
      arguments[3] = parseInt(arguments[2]);
      arguments[2] = 'EX';
    }
    if (typeof arguments[2] === 'undefined') {
      arguments = [arguments[0], arguments[1]];
    }
    return await redis.set.apply(redis, arguments);
  }

  redis.getJSON = async key => {
    const value = await redis.get(key);
    if (value) {
      return JSON.parse(value);
    }
    return value;
  }

  return redis;
};

Fix redis syntax error if third argument is undefined


const Command = require('../structures/command.js');
const request = require('request');

module.exports = class TogetherTube extends Command {

  constructor(client) {
    super(client);
    this.name = "togethertube";
    this.aliases ["ttube", "ttb"];
  }

  run(message, args, commandLang) {
    let embed = this.client.getDekuEmbed(message);
    message.channel.startTyping();
    request('https://togethertube.com/room/create', (error, response) => {
      if (error) {
        embed.setColor(this.client.config.colors.error);
        embed.setTitle(commandLang.error_title);
        embed.setDescription(commandLang.error_description);
      } else {
        embed.setDescription(response.request.uri.href);
        embed.setAuthor('TogetherTube', 'https://togethertube.com/assets/img/favicons/favicon-32x32.png', 'https://togethertube.com/');
        message.channel.stopTyping();
        message.channel.send({embed});
      }
    });
  }

}

const Command = require('../structures/command.js');
const request = require('request');

module.exports = class TogetherTube extends Command {

  constructor(client) {
    super(client);
    this.name    = "togethertube";
    this.aliases = ["ttube", "ttb"];
  }

  run(message, args, commandLang) {
    let embed = this.client.getDekuEmbed(message);
    message.channel.startTyping();
    request('https://togethertube.com/room/create', (error, response) => {
      if (error) {
        embed.setColor(this.client.config.colors.error);
        embed.setTitle(commandLang.error_title);
        embed.setDescription(commandLang.error_description);
      } else {
        embed.setDescription(response.request.uri.href);
        embed.setAuthor('TogetherTube', 'https://togethertube.com/assets/img/favicons/favicon-32x32.png', 'https://togethertube.com/');
      }
      message.channel.stopTyping();
        message.channel.send({embed});
    });
  }

}

Fix aliases and error message.g

Fix aliases and error message.g


import DS from 'ember-data';
import OsfModel from 'ember-osf/models/osf-model';

/**
 * @module ember-preprints
 * @submodule models
 */

/**
 * Model for OSF APIv2 preprints. This model may be used with one of several API endpoints. It may be queried directly. In the future, there will be multiple taxonomy endpoints under the same namespace.
 * For field and usage information, see:
 * https://api.osf.io/v2/docs/#!/v2/Plos_Taxonomy_GET
 * @class Taxonomy
 */
export default OsfModel.extend({
    type: DS.attr('string'),
    text: DS.attr('string'),
    // TODO: Api implements this as a list field for now. This should be a relationship field in the future, when API supports it
    parentIds: DS.attr(),
});

import DS from 'ember-data';
import OsfModel from 'ember-osf/models/osf-model';

/**
 * @module ember-preprints
 * @submodule models
 */

/**
 * Model for OSF APIv2 preprints. This model may be used with one of several API endpoints. It may be queried directly. In the future, there will be multiple taxonomy endpoints under the same namespace.
 * For field and usage information, see:
 * https://api.osf.io/v2/docs/#!/v2/Plos_Taxonomy_GET
 * @class Taxonomy
 */
export default OsfModel.extend({
    type: DS.attr('string'),
    text: DS.attr('string'),
    parents: DS.attr(),
});

Update field name -remove TODO

Update field name
    -remove TODO


/**
 * Created by jonathan on 3/7/15.
 */

var CameraApp = function() {};

CameraApp.prototype = {
    framesPerSecond: 1,

    setup: function() {
        this.image = document.getElementById('CameraImage');
        this.imageSource = 'http://104.206.193.11:49709/dcnvr/video/live/image/2?w=320&h=240';
        this.loadImage();
    },

    loadImage: function() {
        var calculatedDelay = 1000 / this.framesPerSecond;
        var currentTime = new Date().getTime();
        if (this.lastLoadTime != undefined){
            calculatedDelay = calculatedDelay - (currentTime - this.lastLoadTime);
        }

        this.lastLoadTime = currentTime;

        if (calculatedDelay <= 0) {
            this.image.src = this.imageSource + '&random=' + Math.random();
        } else {
            var cameraApp = this;
            this.timer = setTimeout(function() {
                cameraApp.image.src = cameraApp.imageSource + '&random=' + Math.random();
            }, calculatedDelay);
        }
    }
};

var cameraApp = null;

$(document).ready(function () {
    cameraApp = new CameraApp();

    $('#CameraImage').load(function() {
        cameraApp.loadImage();
    });

    cameraApp.setup();
});

/**
 * Created by jonathan on 3/7/15.
 */

var CameraApp = function() {};

CameraApp.prototype = {
    framesPerSecond: 1,
    timeoutInMinutes: 1,

    setup: function() {
        this.startTime = new Date().getTime();
        this.image = document.getElementById('CameraImage');
        this.imageSource = 'http://104.206.193.11:49709/dcnvr/video/live/image/2?w=320&h=240';
        this.loadImage();
    },

    loadImage: function() {
        var calculatedDelay = 1000 / this.framesPerSecond;
        var currentTime = new Date().getTime();

        if (currentTime - this.startTime > this.timeoutInMinutes * 60000)
        {
            if (!confirm('Live video viewing has timed out. Do you want to continue viewing?'))
            {
                return;
            } else {
                this.startTime = new Date().getTime();
            }
        }

        if (this.lastLoadTime != undefined){
            calculatedDelay = calculatedDelay - (currentTime - this.lastLoadTime);
        }

        this.lastLoadTime = currentTime;

        if (calculatedDelay <= 0) {
            this.image.src = this.imageSource + '&random=' + Math.random();
        } else {
            var cameraApp = this;
            this.timer = setTimeout(function() {
                cameraApp.image.src = cameraApp.imageSource + '&random=' + Math.random();
            }, calculatedDelay);
        }
    }
};

var cameraApp = null;

$(document).ready(function () {
    cameraApp = new CameraApp();

    $('#CameraImage').load(function() {
        cameraApp.loadImage();
    });

    cameraApp.setup();
});

Add live video feed timeout

Add live video feed timeout


import patchNode from '../node/patch';
import Transaction from '../transaction';
import { CreateNodeHookCache, VTree } from '../util/types';
import globalThis from '../util/global';

/**
 * Processes a set of patches onto a tracked DOM Node.
 *
 * @param {Transaction} transaction
 * @return {void}
 */
export default function patch(transaction) {
  const { mount, state, patches } = transaction;
  const { mutationObserver, measure, scriptsToExecute } = state;

  measure('patch node');

  const { ownerDocument } = /** @type {HTMLElement} */ (mount);
  const promises = transaction.promises || [];

  state.ownerDocument = ownerDocument || globalThis.document;

  // Always disconnect a MutationObserver before patching.
  if (mutationObserver) {
    mutationObserver.disconnect();
  }

  // Hook into the Node creation process to find all script tags, and mark them
  // for execution.
  const collectScripts = (/** @type {VTree} */vTree) => {
    if (vTree.nodeName === 'script') {
      scriptsToExecute.set(vTree, vTree.attributes.type);
    }
  };

  CreateNodeHookCache.add(collectScripts);

  // Skip patching completely if we aren't in a DOM environment.
  if (state.ownerDocument) {
    promises.push(...patchNode(patches, state));
  }

  CreateNodeHookCache.delete(collectScripts);

  transaction.promises = promises;
  measure('patch node');
}

import patch from '../node/patch';
import Transaction from '../transaction';
import { CreateNodeHookCache, VTree } from '../util/types';
import globalThis from '../util/global';

/**
 * Processes a set of patches onto a tracked DOM Node.
 *
 * @param {Transaction} transaction
 * @return {void}
 */
export default function patchNode(transaction) {
  const { mount, state, patches } = transaction;
  const { mutationObserver, measure, scriptsToExecute } = state;

  measure('patch node');

  const { ownerDocument } = /** @type {HTMLElement} */ (mount);
  const promises = transaction.promises || [];

  state.ownerDocument = ownerDocument || globalThis.document;

  // Always disconnect a MutationObserver before patching.
  if (mutationObserver) {
    mutationObserver.disconnect();
  }

  // Hook into the Node creation process to find all script tags, and mark them
  // for execution.
  const collectScripts = (/** @type {VTree} */vTree) => {
    if (vTree.nodeName === 'script') {
      scriptsToExecute.set(vTree, vTree.attributes.type);
    }
  };

  CreateNodeHookCache.add(collectScripts);

  // Skip patching completely if we aren't in a DOM environment.
  if (state.ownerDocument) {
    promises.push(...patch(patches, state));
  }

  CreateNodeHookCache.delete(collectScripts);

  transaction.promises = promises;
  measure('patch node');
}

Rename public function to match task name


var url = require("url");
var qs = require("qs");

/**
 * getNextLink
 * @function
 * @param {Object} response A response object returned from calling 'client.makeRequest'
 * @returns A parsed version of the link to the subsequent page, or null if no such page exists.
 */
var getNextLink = function (response) {
	if (response.headers.link) {
		var links = response.headers.link.split(",");
		for (var elem in links) {
			if (links[elem].includes("rel=\"next\"")) {
				var linkRegex = /<(.*)>/;
				var link = linkRegex.exec(links[elem])[1];
				var parsedUrl = url.parse(link);
				return qs.parse(parsedUrl.query);
			}
		}
	}
	return null;
};

module.exports.getNextLink = getNextLink;

var url = require("url");
var qs = require("qs");

/**
 * getNextLink
 * @function
 * @param {Object} response A response object returned from calling 'client.makeRequest'
 * @returns A parsed version of the link to the subsequent page, or null if no such page exists.
 */
var getNextLink = function (response) {
	if (response.headers.link) {
		var links = response.headers.link.split(",");
		for (var elem in links) {
			if (links[elem].indexOf("rel=\"next\"") !== -1) {
				var linkRegex = /<(.*)>/;
				var link = linkRegex.exec(links[elem])[1];
				var parsedUrl = url.parse(link);
				return qs.parse(parsedUrl.query);
			}
		}
	}
	return null;
};

module.exports.getNextLink = getNextLink;

Switch string.incluldes() to string.indexOf() for compatibility reasons


// Remove duplicate elements from array

function removeDups(arr){
  var dupes ={},
      returnArray = [],
      el;

  for(var i =0; i<arr.length; i++){
    el = arr[i];
    if(!dupes[el]){
      returnArray.push(el);
      dupes[el] = true;
   }
  }
  return returnArray;
}

removeDups([1,3,3,3,1,5,6,7,8,1]);

// Remove duplicate elements from array

function removeDups(arr){
  var dupes ={},
      returnArray = [],
      el;

  for(var i =0; i<arr.length; i++){
    el = arr[i];
    if(!dupes[el]){
      returnArray.push(el);
      dupes[el] = true;
   }
  }
  return returnArray;
}

removeDups([10,30,3,30,3,10,5,6,7,8,1,1, 'test', 'test']);

Remove duplicate elements in an array (FIX)


import webpack from 'webpack';
import {BundleAnalyzerPlugin} from 'webpack-bundle-analyzer';
import config from '../webpack.config.prod';

config.plugins.push(new BundleAnalyzerPlugin());

const compiler = webpack(config);

compiler.run((error, stats) => {
  if (error) {
    throw new Error(error);
  }

  console.log(stats); // eslint-disable-line no-console
});

import webpack from 'webpack';
import {BundleAnalyzerPlugin} from 'webpack-bundle-analyzer';
import config from '../webpack.config.prod';

config.plugins.push(new BundleAnalyzerPlugin());

process.env.NODE_ENV = 'production';

const compiler = webpack(config);

compiler.run((error, stats) => {
  if (error) {
    throw new Error(error);
  }

  console.log(stats); // eslint-disable-line no-console
});

Set prod env when analyzing bundle

Set prod env when analyzing bundle


import $ from 'jquery';
import Router from './util/router';
import common from './routes/Common';
import home from './routes/Home';
import about_us from './routes/About';

// Import Bootstrap
import 'bootstrap/dist/js/umd/util.js';
import 'bootstrap/dist/js/umd/alert.js';
import 'bootstrap/dist/js/umd/button.js';
import 'bootstrap/dist/js/umd/carousel.js';
import 'bootstrap/dist/js/umd/collapse.js';
import 'bootstrap/dist/js/umd/dropdown.js';
import 'bootstrap/dist/js/umd/modal.js';
import 'bootstrap/dist/js/umd/scrollspy.js';
import 'bootstrap/dist/js/umd/tab.js';
import 'bootstrap/dist/js/umd/tooltip.js';
import 'bootstrap/dist/js/umd/popover.js';

// Use this variable to set up the common and page specific functions. If you
// rename this variable, you will also need to rename the namespace below.
const routes = {
  // All pages
  common,
  // Home page
  home,
  // About us page, note the change from about-us to about_us.
  about_us
};

// Load Events
$(document).ready(() => new Router(routes).loadEvents());

import $ from 'jquery';
import Router from './util/router';
import common from './routes/Common';
import home from './routes/Home';
import about_us from './routes/About';

// Import npm dependencies
import 'bootstrap/dist/js/umd/util.js';
import 'bootstrap/dist/js/umd/alert.js';
import 'bootstrap/dist/js/umd/button.js';
import 'bootstrap/dist/js/umd/carousel.js';
import 'bootstrap/dist/js/umd/collapse.js';
import 'bootstrap/dist/js/umd/dropdown.js';
import 'bootstrap/dist/js/umd/modal.js';
import 'bootstrap/dist/js/umd/scrollspy.js';
import 'bootstrap/dist/js/umd/tab.js';
import 'bootstrap/dist/js/umd/tooltip.js';
import 'bootstrap/dist/js/umd/popover.js';

// Use this variable to set up the common and page specific functions. If you
// rename this variable, you will also need to rename the namespace below.
const routes = {
  // All pages
  common,
  // Home page
  home,
  // About us page, note the change from about-us to about_us.
  about_us
};

// Load Events
$(document).ready(() => new Router(routes).loadEvents());

Update comment for importing deps

Update comment for importing deps


var geocoder = require('node-geocoder') ("google", "https", {
	apiKey: '<YOUR-KEY>'
});
var csv = require('csv');

process.stdin
	.pipe(csv.parse())
	.pipe(csv.transform(function(data, callback){
		setImmediate(function(){
			geocoder.geocode(data[1])
		    .then(function(res) {
				data.push(res[0].latitude);
				data.push(res[0].longitude);
				callback(null, data);
		    })
		    .catch(function(err) {
		        console.log(data[0] + " " + err);
		    });
		});}, {parallel: 20}))
	.pipe(csv.stringify({quotedString: true}))
	.pipe(process.stdout);

var apiKey = "<YOUR-KEY>";
var geocoder = require('node-geocoder') ("google", "https", { apiKey: apiKey });
var csv = require('csv');

process.stdin
	.pipe(csv.parse())
	.pipe(csv.transform(function(data, callback){
		setImmediate(function(){
			geocoder.geocode(data[1])
		    .then(function(res) {
				data.push(res[0].latitude);
				data.push(res[0].longitude);
				callback(null, data);
		    })
		    .catch(function(err) {
		        console.log(data[0] + " " + err);
		    });
		});}, {parallel: 20}))
	.pipe(csv.stringify({quotedString: true}))
	.pipe(process.stdout);

Relocate the key to be able to find it eaven easier


'use strict';

var gulp = require('gulp');

var files = ['manifest.json', 'background.js'];
var xpiName = 'catgifs.xpi';

gulp.task('default', function () {
  console.log(files, xpiName)
});

'use strict';

var gulp = require('gulp');
var zip = require('gulp-zip');

var files = ['manifest.json', 'background.js'];
var xpiName = 'catgifs.xpi';

gulp.task('default', function () {
  gulp.src(files)
    .pipe(zip(xpiName))
    .pipe(gulp.dest('.'));
});

Use gulp to create the xpi.

Use gulp to create the xpi.


var gulp = require('gulp');
var shell = require('gulp-shell');
var tsc = require('gulp-tsc');

gulp.task('build', function () {
  return gulp.src([
      './**/*.ts',
      '!./node_modules/**/*.ts'
    ])
    .pipe(tsc({
      target: 'ES5',
      removeComments: true,
      sourceMap: true
    }))
    .pipe(gulp.dest('.'));
});

gulp.task('run', [ 'build' ], shell.task([
  'node main.js'
]));

var gulp = require('gulp');
var shell = require('gulp-shell');
var tsc = require('gulp-tsc');

gulp.task('build', function () {
  return gulp.src([
      './**/*.ts',
      '!./node_modules/**/*.ts'
    ])
    .pipe(tsc({
      target: 'ES5',
      removeComments: true,
      sourceMap: true
    }))
    .pipe(gulp.dest('.'));
});

gulp.task('run', [ 'build' ], shell.task([
  'NODE_PATH=$NODE_PATH:./lib node main.js'
]));

Add lib to NODE_PATH when running the app.


'use strict';

var gulp = require('gulp');

var options = {
  name: 'ec2prices',
  dependantFiles: ['node_modules/babel/browser-polyfill.js'],
  mainFiles: [
    'app/scripts/app.es6',
    'app/scripts/**/!(*.spec|*.mock).{js,es6}'
  ],
  templateFiles: ['app/scripts/**/*.htm{,l}'],
  specFiles: ['app/scripts/**/*.{spec,mock}.es6'],

  views: {
    src: ['app/views/{,*/}*.htm{,l}'],
    base: 'app/views/'
  },
  normalFiles: ['app/instances.json'],
  buildDir: 'build',
  version: false,
};

require('./gulp/copy.js')(options);
require('./gulp/css.js')(options);
require('./gulp/deploy.js')(options);
require('./gulp/html.js')(options);
require('./gulp/js.js')(options);
require('./gulp/lint.js')(options);
require('./gulp/serve.js')(options);
require('./gulp/tests.js')(options);

gulp.task('default', ['lint', 'js', 'html', 'copy', 'css']);

'use strict';

var gulp = require('gulp');

var options = {
  name: 'ec2prices',
  dependantFiles: ['node_modules/babel/browser-polyfill.js'],
  mainFiles: [
    'app/scripts/app.es6',
    'app/scripts/**/!(*.spec|*.mock).{js,es6}'
  ],
  templateFiles: ['app/scripts/**/*.htm{,l}'],
  specFiles: ['app/scripts/**/*.{spec,mock}.es6'],

  views: {
    src: ['app/views/{,*/}*.htm{,l}'],
    base: 'app/views/'
  },
  normalFiles: ['app/instances.json'],
  buildDir: 'build',
  version: false,
};

require('./gulp/copy.js')(options);
require('./gulp/css.js')(options);
require('./gulp/deploy.js')(options);
require('./gulp/html.js')(options);
require('./gulp/js.js')(options);
require('./gulp/lint.js')(options);
require('./gulp/serve.js')(options);
require('./gulp/tests.js')(options);

gulp.task('default', ['lint', 'test', 'js', 'html', 'copy', 'css']);

Add the test task dependency back to the default gulp task


var parse = require('./parse');
var clean = require('./clean');

module.exports = Engine = {};

var pythons = [];
var outputs = [];
var pythonNum = 0;

Engine.runPython = function(operation, a, b, cb) {
  if (operation === 'local' || operation === 'global') {
    var cleanup = clean.cleanMin(operation, a, b, cb);
    a   = cleanup.func;
    b   = cleanup.options;
    cb  = cleanup.callback;
    b = JSON.stringify(b);
  } else if (operation === 'nnls') {
    cb = clean.cleanCB(cb);
    a = JSON.stringify(a);
    b = JSON.stringify(b);
  }

  // immediately invoked function in case user invokes runPython multiple times,
  // starting multiple child processes, causing race condition,
  // causing stdouts to potentially overlap.
  (function (num){
    pythons[num] = require('child_process').spawn(
      'python',
      [__dirname + '/../py/exec.py', operation, a, b]);
    outputs[num] = '';
    pythons[num].stdout.on('data', function(data){
      outputs[num] += data;
    });
    pythons[num].stdout.on('close', function(){
      // cb(outputs[num]);
      cb(JSON.parse(outputs[num]));
    });
  })(pythonNum++)
}

var parse = require('./parse');
var clean = require('./clean');

module.exports = Engine = {};

var pythons = [];
var outputs = [];
var pythonNum = 0;

Engine.runPython = function(operation, a, b, cb, xData, yData) {
  if (operation === 'local' || operation === 'global') {
    var cleanup = clean.cleanMin(operation, a, b, cb);
    a   = cleanup.func;
    b   = cleanup.options;
    cb  = cleanup.callback;
    b = JSON.stringify(b);
  } else if (operation === 'nnls') {
    cb = clean.cleanCB(cb);
    a = JSON.stringify(a);
    b = JSON.stringify(b);
  } else if (operation === 'fit') {
    var cleanup = clean.cleanFit(a, b, cb, xData, yData);
    a = cleanup.func;
    b = cleanup.options;
    cb = cleanup.callback;
    b = JSON.stringify(b);
  }

  // immediately invoked function in case user invokes runPython multiple times,
  // starting multiple child processes, causing race condition,
  // causing stdouts to potentially overlap (otherwise).
  (function (num){
    pythons[num] = require('child_process').spawn(
      'python',
      [__dirname + '/../py/exec.py', operation, a, b]);
    outputs[num] = '';
    pythons[num].stdout.on('data', function(data){
      outputs[num] += data;
    });
    pythons[num].stdout.on('close', function(){
      // cb(outputs[num]);
      cb(JSON.parse(outputs[num]));
    });
  })(pythonNum++)
}

Add specification for fit operation

Add specification for fit operation


import { Mongo } from 'meteor/mongo';
import { SimpleSchema } from 'meteor/aldeed:simple-schema';

class ModuleFulfilmentCollection extends Mongo.Collection {
  insert(fulfilmentData, callBack){
    const fulfilmentDoc = fulfilmentData;
    let result;
    //validate document
    return super.insert( fulfilmentDoc, callBack);
  };
  update(selector, modifier){
    const result = super.update(selector, modifier);

    return result;
  };

  remove(selector){
    const result = super.remove(selector);
    return result;
  };
}

export const ModuleFulfilments = new ModuleFulfilmentCollection("modfulfilment");

/*
 * moduleMapping type,
 * @key academicYear
 * @value moduleMapping object
 */
const fulfilmentSchema = {
  moduleCode: {
    type: String
  },
  moduleMapping: {
    type: object,
    blackbox: true
  }
}

ModuleFulfilments.attachSchema(fulfilmentSchema);

import { Mongo } from 'meteor/mongo';
import { SimpleSchema } from 'meteor/aldeed:simple-schema';

class ModuleFulfilmentCollection extends Mongo.Collection {
  insert(fulfilmentData, callBack){
    const fulfilmentDoc = fulfilmentData;
    let result;
    //validate document
    return super.insert( fulfilmentDoc, callBack);
  };
  update(selector, modifier){
    const result = super.update(selector, modifier);

    return result;
  };

  remove(selector){
    const result = super.remove(selector);
    return result;
  };
}

export const ModuleFulfilments = new ModuleFulfilmentCollection("modfulfilment");

/*
 * moduleMapping type,
 * @key academicYear
 * @value moduleMapping object
 */
const fulfilmentSchema = {
  moduleCode: {
    type: String
  },
  moduleMapping: {
    type: Object,
    blackbox: true
  }
}

ModuleFulfilments.attachSchema(fulfilmentSchema);

FIX wrong db schema declaration

FIX wrong db schema declaration


var config = {
    /** app mode **/
    mode: 'DEV',

    /** db name **/
    db: 'tiapp-exercise',

    /** android tablet minimum form factor **/
    tablet: {
        width: 899,
        height: 899
    },

    /** Actions **/
    action: [
        {module: 'Try',     name: 'doSave',         path: 'Como.Controller.Try.doSave'},
        {module: 'Try',     name: 'showLogin',      path: 'Como.Controller.Try.showLogin'},
        {module: 'Try',     name: 'doLogin',        path: 'Como.Controller.Try.doLogin'},
        {module: 'Try',     name: 'doLogout',       path: 'Como.Controller.Try.doLogout'}
    ]
};

module.exports = config;

var config = {
    /** app mode **/
    mode: 'DEV',

    /** db name **/
    db: 'tiapp-como',

    /** android tablet minimum form factor **/
    tablet: {
        width: 899,
        height: 899
    },

    /** Actions **/
    action: [
        {module: 'Try',     name: 'doSave',         path: 'Como.Controller.Try.doSave'},
        {module: 'Try',     name: 'showLogin',      path: 'Como.Controller.Try.showLogin'},
        {module: 'Try',     name: 'doLogin',        path: 'Como.Controller.Try.doLogin'},
        {module: 'Try',     name: 'doLogout',       path: 'Como.Controller.Try.doLogout'}
    ]
};

module.exports = config;

Update to change db name on config

Update to change db name on config


'use strict';

var grunt = require('grunt');

/*
 ======== A Handy Little Nodeunit Reference ========
 https://github.com/caolan/nodeunit

 Test methods:
 test.expect(numAssertions)
 test.done()
 Test assertions:
 test.ok(value, [message])
 test.equal(actual, expected, [message])
 test.notEqual(actual, expected, [message])
 test.deepEqual(actual, expected, [message])
 test.notDeepEqual(actual, expected, [message])
 test.strictEqual(actual, expected, [message])
 test.notStrictEqual(actual, expected, [message])
 test.throws(block, [error], [message])
 test.doesNotThrow(block, [error], [message])
 test.ifError(value)
 */

exports.autoprefixer = {
    setUp: function (done) {
        // setup here if necessary
        done();
    },
    default_options: function (test) {
        test.expect(1);

        var actual = grunt.file.read('tmp/default_options.css');
        var expected = grunt.file.read('test/expected/default_options.css');
        test.strictEqual(actual, expected, 'should describe what the default behavior is.');

        test.done();
    },
    custom_options: function (test) {
        test.expect(1);

        var actual = grunt.file.read('tmp/custom_options.css');
        var expected = grunt.file.read('test/expected/custom_options.css');
        test.strictEqual(actual, expected, 'should describe what the custom option(s) behavior is.');

        test.done();
    },
};

'use strict';

var grunt = require('grunt');

/*
 ======== A Handy Little Nodeunit Reference ========
 https://github.com/caolan/nodeunit

 Test methods:
 test.expect(numAssertions)
 test.done()
 Test assertions:
 test.ok(value, [message])
 test.equal(actual, expected, [message])
 test.notEqual(actual, expected, [message])
 test.deepEqual(actual, expected, [message])
 test.notDeepEqual(actual, expected, [message])
 test.strictEqual(actual, expected, [message])
 test.notStrictEqual(actual, expected, [message])
 test.throws(block, [error], [message])
 test.doesNotThrow(block, [error], [message])
 test.ifError(value)
 */

exports.autoprefixer = {
    setUp: function (done) {
        // setup here if necessary
        done();
    },
    custom_options: function (test) {
        test.expect(1);

        var actual = grunt.file.read('tmp/custom_options.css');
        var expected = grunt.file.read('test/expected/custom_options.css');
        test.strictEqual(actual, expected, 'should describe what the custom option(s) behavior is.');

        test.done();
    },
};

Remove test for default options

Remove test for default options


/* jshint node: true */

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

/* jshint node: true */

/* ==================
 * USAGE INSTRUCTIONS
 * ==================
 *
 * If you'd like to make a local change to this file, you need
 * to tell git to ignore any changes to this file. You can do
 * this by running:
 *
 * git update-index --skip-worktree [file-path]
 *
 * If you want to undo the ignore and actually commit changes:
 *
 * git update-index --no-skip-worktree [file-path]
 *
 */

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

Add usage instructions to config blueprint


// Basic idea from Bojan Mihelac -
// http://source.mihelac.org/2010/02/19/django-time-widget-custom-time-shortcuts/

// Django imports jQuery into the admin site using noConflict(True)
// We wrap this in an anonymous function to stick to jQuery's $ idiom
// and ensure we're using the admin version of jQuery, rather than
// anything else pulled in

(function($) {
   var Schedule = {
      init: function() {
         time_format = get_format('TIME_INPUT_FORMATS')[0];
         $(".timelist").each(function(num) {
            // Clear existing list
            $( this ).empty();
            // Fill list with time values
            for (i=8; i < 20; i++) {
               var time = new Date(1970,1,1,i,0,0);
               quickElement("a", quickElement("li", this, ""),
                  time.strftime(time_format), "href",
                  "javascript:DateTimeShortcuts.handleClockQuicklink(" + num +
                  ", " + i + ");");
            }
         });
      }
   }

   // We need to be called after django's DateTimeShortcuts.init, which
   // is triggered by a load event
   $( window ).bind('load', Schedule.init);
}(django.jQuery));

// Override the default setting on the django admin DateTimeShortcut
// Django 2 nicely does make this overridable, but we need to
// set it up before the DateTimeShortcuts init is called by
// window.onload, so we attach it to DOMContentLoaded
//
// The names of the input fields are also a bit opaque, and
// unfornately not something we can easily pass in

document.addEventListener("DOMContentLoaded", function() {
   console.log(window.DateTimeShortcuts);
   // These are for the single admin pages
   window.DateTimeShortcuts.clockHours.end_time_1 = [];
   window.DateTimeShortcuts.clockHours.start_time_1 = [];
   for (let hour = 8; hour <= 20; hour++) {
       let verbose_name = new Date(1970, 1, 1, hour, 0, 0).strftime('%H:%M');
       window.DateTimeShortcuts.clockHours.end_time_1.push([verbose_name, hour])
       window.DateTimeShortcuts.clockHours.start_time_1.push([verbose_name, hour])
   }
   // This is for the inline options - we define 30, which is hopefully sane
   for (let inline = 0; inline < 30; inline++) {
      let name = 'form-' + inline + '-end_time_1';
      console.log('computed name: ' + name);
      window.DateTimeShortcuts.clockHours[name] = [];
      for (let hour = 8; hour <= 20; hour++) {
          let verbose_name = new Date(1970, 1, 1, hour, 0, 0).strftime('%H:%M');
          window.DateTimeShortcuts.clockHours[name].push([verbose_name, hour])
      }
   }
});

Rework the scheduletime helper to work with later admintimewidget helper code


var expect = require('chai').expect,
    request = require('superagent').agent(),
    PrettyCSS = require('PrettyCSS'),
    testhost = require('../src/server').testhost();

describe('fields.css', function() {
    var res;
    before(function (done) {
        request.get(testhost + '/css/fields.css').end(function(r) {
            res = r;
            done();
        });
    });
    it('has text/css content-type', function() {
        expect(res.type).to.equal('text/css');
    });

    it('is valid CSS', function() {
        expect(PrettyCSS.parse(res.text).errors.length).to.equal(0);
    });
});

/*describe('svc/bndb_initializer', function() {
    var res;
    before(function (done) {
        request.get(testhost + '/svc/bndb_initializer.js').end(function(r) {
            res = r;
            done();
        });
    });
    it('has text/javascript content-type', function() {
        expect(res.type).to.equal('text/javascript');
    });

    it('valid JS', function() {
        expect(jshint(res.text)).to.equal(true);
    });
});*/

var expect = require('chai').expect,
    request = require('superagent').agent(),
    PrettyCSS = require('PrettyCSS'),
    Q = require('q'),
    connect = Q.defer(),
    environment = require('./lib/environment').default;

require('../src/server').harness(function (url) {
    connect.resolve(url);
});

describe('fields.css', function() {
    var res;
    before(function (done) {
        connect.promise.done(function (testhost) {
            request.get(testhost + '/css/fields.css').end(function(r) {
                res = r;
                done();
            });
        });
    });
    it('has text/css content-type', function() {
        expect(res.type).to.equal('text/css');
    });

    it('is valid CSS', function() {
        expect(PrettyCSS.parse(res.text).errors.length).to.equal(0);
    });
});

/*describe('svc/bndb_initializer', function() {
    var res;
    before(function (done) {
        request.get(testhost + '/svc/bndb_initializer.js').end(function(r) {
            res = r;
            done();
        });
    });
    it('has text/javascript content-type', function() {
        expect(res.type).to.equal('text/javascript');
    });

    it('valid JS', function() {
        expect(jshint(res.text)).to.equal(true);
    });
});*/

Use new harness in generated assets unit test


import normalizeArgs, { __RewireAPI__ as rewireAPI } from '../../../src/server/process/normalizeArgs';

describe('normalizeArgs', () => {
    afterEach(() => {
        rewireAPI.__ResetDependency__('process');
    });

    it('should normalize for Windows with no COMSPEC', () => {
        rewireAPI.__Rewire__('process', {
            platform: 'win32',
            env: {}
        });

        const result = normalizeArgs('echo Hello world');
        expect(result).toEqual({
            file: 'cmd.exe',
            args: ['/s', '/c', '"echo Hello world"'],
            options: { windowsVerbatimArguments: true }
        });
    });

    it('should normalize for Windows with COMSPEC defined', () => {
        rewireAPI.__Rewire__('process', {
            platform: 'win32',
            env: { comspec: 'command.com' }
        });

        const result = normalizeArgs('echo Hello again');
        expect(result).toEqual({
            file: 'command.com',
            args: ['/s', '/c', '"echo Hello again"'],
            options: { windowsVerbatimArguments: true }
        });
    });

    it('should normalize for Unix-like systems', () => {
        rewireAPI.__Rewire__('process', {
            platform: 'darwin'
        });

        const result = normalizeArgs('echo Hello from the other side');
        expect(result).toEqual({
            file: '/bin/sh',
            args: ['-c', 'echo Hello from the other side'],
            options: {}
        });
    });
});

import normalizeArgs, { __RewireAPI__ as rewireAPI } from '../../../src/server/process/normalizeArgs';

describe('normalizeArgs', () => {
    afterEach(() => {
        rewireAPI.__ResetDependency__('process');
    });

    it('should normalize for Windows with no COMSPEC', () => {
        rewireAPI.__Rewire__('process', {
            platform: 'win32',
            env: {}
        });

        const result = normalizeArgs('echo Hello world');
        expect(result).toEqual({
            file: 'cmd.exe',
            args: ['/s', '/c', 'echo Hello world'],
            options: { windowsVerbatimArguments: true }
        });
    });

    it('should normalize for Windows with COMSPEC defined', () => {
        rewireAPI.__Rewire__('process', {
            platform: 'win32',
            env: { comspec: 'command.com' }
        });

        const result = normalizeArgs('echo Hello again');
        expect(result).toEqual({
            file: 'command.com',
            args: ['/s', '/c', 'echo Hello again'],
            options: { windowsVerbatimArguments: true }
        });
    });

    it('should normalize for Unix-like systems', () => {
        rewireAPI.__Rewire__('process', {
            platform: 'darwin'
        });

        const result = normalizeArgs('echo Hello from the other side');
        expect(result).toEqual({
            file: '/bin/sh',
            args: ['-c', 'echo Hello from the other side'],
            options: {}
        });
    });
});

Remove quotes from tests in normalizeArgs


import App from './app';
import 'babel-polyfill';
common.app = new App(common);
common.app.start();

import App from './app';
common.app = new App(common);
common.app.start();

Remove babel-polyfill import in man.js

Remove babel-polyfill import in man.js


"use strict";

const apiRequest = require( "../../src/token/api-request" );
const storeToken = require( "../../src/token/store-token" );
const Promise = require( "bluebird" );
const expect = require( "expect.js" );
const sinonSandbox = require( "sinon" ).sandbox.create();

describe.only( "Generative testing", function() {
  ["SOME", "RANDOM", "STRINGS"].forEach(function( randomString ) {
    describe( `Given the token '${randomString}'`, function() {
      let fakeToken;

      beforeEach(function() {
        fakeToken = randomString
      });

      describe( `When storing the token '${randomString}'`, function() {
        let promiseToStoreToken;
        let mockedApiRequest;

        beforeEach(function() {
          mockedApiRequest = sinonSandbox
            .mock( apiRequest )
            .expects( "post" )
            .withExactArgs( "/store-token", fakeToken );
          promiseToStoreToken = storeToken( fakeToken, apiRequest );
        });

        afterEach(function() {
          sinonSandbox.restore();
        });

        it( "persists", function() {
          return Promise.try(function() {
            return promiseToStoreToken;
          }).then(function() {
            mockedApiRequest.verify();
          });
        });
      });
    });
  });
});

"use strict";

const apiRequest = require( "../../src/token/api-request" );
const storeToken = require( "../../src/token/store-token" );
const Promise = require( "bluebird" );
const expect = require( "expect.js" );
const sinonSandbox = require( "sinon" ).sandbox.create();

describe( "Generative testing", function() {
  ["SOME", "RANDOM", "STRINGS"].forEach(function( randomString ) {
    describe( `Given the token '${randomString}'`, function() {
      let fakeToken;

      beforeEach(function() {
        fakeToken = randomString
      });

      describe( `When storing the token '${randomString}'`, function() {
        let promiseToStoreToken;
        let mockedApiRequest;

        beforeEach(function() {
          mockedApiRequest = sinonSandbox
            .mock( apiRequest )
            .expects( "post" )
            .withExactArgs( "/store-token", fakeToken );
          promiseToStoreToken = storeToken( fakeToken, apiRequest );
        });

        afterEach(function() {
          sinonSandbox.restore();
        });

        it( "persists", function() {
          return Promise.try(function() {
            return promiseToStoreToken;
          }).then(function() {
            mockedApiRequest.verify();
          });
        });
      });
    });
  });
});

Remove the .only from the generative test


formsAngular.filter('titleCase',[function() {
    return function(str, stripSpaces) {
        var value = str.replace(/(_|\.)/g, ' ').replace(/[A-Z]/g, ' $&').replace(/\w\S*/g, function (txt) {
            return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
        });
        if (stripSpaces) {
            value = value.replace(/\s/g,'');
        }
        return value;
    }
}]);

formsAngular.filter('titleCase',[function() {
    return function(str, stripSpaces) {
        var value = str.replace(/(_|\.)/g, ' ').replace(/[a-z][A-Z]/g, ' $&').replace(/\w\S*/g, function (txt) {
            return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
        });
        if (stripSpaces) {
            value = value.replace(/\s/g,'');
        }
        return value;
    }
}]);

Stop titleCase introducing double spaces


import Em from 'ember';
import LlamaBodyCell from 'llama-table/components/llama-body-cell/component';
import layout from 'dummy/templates/components/button-cell';
var computed = Em.computed;
var gt = computed.gt;
var not = computed.not;

var ButtonCell = LlamaBodyCell.extend({
	layout: layout,
	showButton: not('isFooter'),
	actions: {
		click: function () {
			var controller = this.get('root');
			var rows = controller.get('rows');
			var row = this.get('content');
			var index = rows.indexOf(row);
			controller.sendAction(this.get('actionName'), index);
		},
	},
});

export default ButtonCell;

import Em from 'ember';
import LlamaBodyCell from 'llama-table/components/llama-body-cell/component';
import layout from 'dummy/templates/components/button-cell';
var computed = Em.computed;
var gt = computed.gt;
var not = computed.not;

var ButtonCell = LlamaBodyCell.extend({
	layout: layout,
	showButton: not('isFooter'),
	actions: {
		click: function () {
			var controller = this.get('root');
			var rows = controller.get('rows');
			var rowController = this.get('content');
			var row = Em.get(rowController, 'content');
			var index = rows.indexOf(row);
			controller.sendAction(this.get('actionName'), index);
		},
	},
});

export default ButtonCell;

Fix remove button in demo table

Fix remove button in demo table


module.exports = function (grunt) {

    grunt.initConfig({
        nodewebkit: {
            options: {
                platforms: ['win', 'osx'],
                buildDir: './build',
                version: '0.12.1'
            },
            src: [
                'index.html',
                'package.json',
                './components/**/*',
                './css/**/*',
                './images/**/*',
                './js/**/*',
                './node_module/**/*'
            ]
        }
    });

    grunt.loadNpmTasks('grunt-node-webkit-builder');

    grunt.registerTask('build', ['nodewebkit']);

};

module.exports = function (grunt) {

    grunt.initConfig({
        nodewebkit: {
            options: {
                platforms: ['win', 'osx', 'linux'],
                buildDir: './build',
                version: '0.12.1'
            },
            src: [
                'index.html',
                'package.json',
                './components/**/*',
                './css/**/*',
                './images/**/*',
                './js/**/*',
                './node_module/**/*'
            ]
        }
    });

    grunt.loadNpmTasks('grunt-node-webkit-builder');

    grunt.registerTask('build', ['nodewebkit']);

};

Add linux in build options

Add linux in build options


'use strict';

module.exports = function(grunt) {

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    jshint: {
      files: ['Gruntfile.js', 'lib/**/*.js'],
      options: {
        globalstrict: true,
        node: true,
        globals: {
          jQuery: true,
          console: false,
          module: true,
          document: true
        }
      }
    },
    mochaTest: {
      test: {
        options: {
          reporter: 'spec'
        },
        src: ['test/**/*.js'],
        env: {
          NODE_ENV: "test"
        }
      }
    }
  });

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

  grunt.registerTask('test-env', function() {process.env.NODE_ENV = "test";});
  grunt.registerTask('test', ['test-env', 'jshint', 'mochaTest' ]);
  grunt.registerTask('default', ['test']);

};

'use strict';

module.exports = function(grunt) {

  grunt.initConfig({
    pkg: grunt.file.readJSON('package.json'),
    jshint: {
      options: {
        globalstrict: true,
        node: true,
        globals: {
          jQuery: true,
          console: false,
          module: true,
          document: true
        }
      }
    },
    mochaTest: {
      test: {
        options: {
          reporter: 'spec'
        },
        src: ['test/**/*.js'],
        env: {
          NODE_ENV: "test"
        }
      }
    }
  });

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

  grunt.registerTask('test-env', function() {process.env.NODE_ENV = "test";});
  grunt.registerTask('test', ['test-env', 'jshint', 'mochaTest' ]);
  grunt.registerTask('default', ['test']);

};

Remove `file` field from jshint configuration.

Tests were failing with message
"Warning: Path must be a string. Received null"

Closes imdone/imdone-core#48


'use strict';

module.exports = function(grunt) {

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        jshint: {
            allFiles: ['Gruntfile.js', 'lib/**/*.js', 'test/**/*.js', 'index.js'],
            options: {
                jshintrc: '.jshintrc',
            }
        },
        mochacli: {
            all: ['test/**/*.js'],
            options: {
                reporter: 'spec',
                ui: 'tdd'
            }
        },
        'mocha_istanbul': {
            coveralls: {
                src: [ 'test/lib', 'test/lib/utils' ],
                options: {
                    coverage: true,
                    legend: true,
                    check: {
                        lines: 100,
                        statements: 99
                    },
                    root: './lib',
                    reportFormats: ['lcov']
                }
            }
        }
    })

    grunt.event.on('coverage', function(lcov, done){
        require('coveralls').handleInput(lcov, function(error) {
            if (error) {
                console.log(error)
                return done(error)
            }
            done()
        })
    })

    // Load the plugins
    grunt.loadNpmTasks('grunt-contrib-jshint')
    grunt.loadNpmTasks('grunt-mocha-cli')
    grunt.loadNpmTasks('grunt-mocha-istanbul')

    // Configure tasks
    grunt.registerTask('coveralls', ['mocha_istanbul:coveralls'])
    grunt.registerTask('default', ['test'])

    grunt.registerTask('test', ['mochacli', 'jshint', 'coveralls'])
}

'use strict';

module.exports = function(grunt) {

    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        jshint: {
            allFiles: ['Gruntfile.js', 'lib/**/*.js', 'test/**/*.js', 'index.js'],
            options: {
                jshintrc: '.jshintrc',
            }
        },
        mochacli: {
            all: ['test/**/*.js'],
            options: {
                reporter: 'spec',
                ui: 'tdd'
            }
        },
        'mocha_istanbul': {
            coveralls: {
                src: [ 'test/lib', 'test/lib/utils' ],
                options: {
                    coverage: true,
                    legend: true,
                    check: {
                        lines: 100,
                        statements: 100
                    },
                    root: './lib',
                    reportFormats: ['lcov']
                }
            }
        }
    })

    grunt.event.on('coverage', function(lcov, done){
        require('coveralls').handleInput(lcov, function(error) {
            if (error) {
                console.log(error)
                return done(error)
            }
            done()
        })
    })

    // Load the plugins
    grunt.loadNpmTasks('grunt-contrib-jshint')
    grunt.loadNpmTasks('grunt-mocha-cli')
    grunt.loadNpmTasks('grunt-mocha-istanbul')

    // Configure tasks
    grunt.registerTask('coveralls', ['mocha_istanbul:coveralls'])
    grunt.registerTask('default', ['test'])

    grunt.registerTask('test', ['mochacli', 'jshint', 'coveralls'])
}

Update coverage values to match current

Update coverage values to match current


module.exports = function(grunt) {

    // TODO: platforms shouldn't be hardcoded here
    var platforms = ['win64'];

    // Build up array of destinations for Twister deamon files
    var destinations = {files: []};
    platforms.forEach(function (platform) {
        destinations.files.push({
                expand: true,
                src: ['./twister-data/**'],
                dest: './builds/Twisting/' + platform + '/'
        });
    });

    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        nodewebkit: {
            options: {
                platforms: platforms,
                buildDir: './builds'
            },
            src: './src/**/*'
        },
        copy: {
            twister: destinations
        },
        less: {
            development: {
                files: {
                    "./src/app/styles/style.css": "./src/app/styles/main.less"
                }
            }
        },
        auto_install: {
            subdir: {
                options: {
                    cwd: 'src',
                    stdout: true,
                    stderr: true,
                    failOnError: true,
                }
            }
        },
    });

    grunt.loadNpmTasks('grunt-node-webkit-builder');
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-contrib-less');
    grunt.loadNpmTasks('grunt-auto-install');

    grunt.registerTask('build', ['less', 'nodewebkit', 'copy:twister']);
    grunt.registerTask('compile', ['less']);
    grunt.registerTask('postinstall', ['auto_install']);
};

module.exports = function(grunt) {

    // TODO: platforms shouldn't be hardcoded here
    var platforms = ['win64'];

    // Build up array of destinations for Twister deamon files
    var destinations = {files: []};
    platforms.forEach(function (platform) {
        destinations.files.push({
                expand: true,
                src: ['./twister-data/**'],
                dest: './builds/Twisting/' + platform + '/'
        });
    });

    // Project configuration.
    grunt.initConfig({
        pkg: grunt.file.readJSON('package.json'),
        nodewebkit: {
            options: {
                platforms: platforms,
                buildDir: './builds'
            },
            src: ['./src/**/*', '!./src/twister-data/**/*', '!./src/*.exe', '!./src/*.pak', '!./src/*.dll']
        },
        copy: {
            twister: destinations
        },
        less: {
            development: {
                files: {
                    "./src/app/styles/style.css": "./src/app/styles/main.less"
                }
            }
        },
        auto_install: {
            subdir: {
                options: {
                    cwd: 'src',
                    stdout: true,
                    stderr: true,
                    failOnError: true,
                }
            }
        },
    });

    grunt.loadNpmTasks('grunt-node-webkit-builder');
    grunt.loadNpmTasks('grunt-contrib-copy');
    grunt.loadNpmTasks('grunt-contrib-less');
    grunt.loadNpmTasks('grunt-auto-install');

    grunt.registerTask('build', ['less', 'nodewebkit', 'copy:twister']);
    grunt.registerTask('compile', ['less']);
    grunt.registerTask('postinstall', ['auto_install']);
};

Fix Grunt file for local testing

Fix Grunt file for local testing


import React from 'react';

import styles from 'stylesheets/components/common/typography';

const Rectangle = () => (

Rechteck

Eingabe

      <form>

          a:
            <input type="text" />

          b:
            <input type="text" />

      </form>

Flächeninhalt

      0

);

export default Rectangle;

import React from 'react';

import styles from 'stylesheets/components/common/typography';

class Rectangle extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      edgeA: 0,
      edgeB: 0,
      area: 0
    };
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(event) {
    const name = event.target.name;
    const value = event.target.value;
    const area =
        name === 'edgeA' ?
        this.computeArea(value, this.state.edgeB):
        this.computeArea(this.state.edgeA, value);

    this.setState({
      [event.target.name]: value,
      area: area
    });
  }

  computeArea(edgeA, edgeB) {
    return edgeA * edgeB;
  }

  render() {
    return (

Rechteck

Eingabe

          <form>

              Seite a:
                <input
                  type="text"
                  name="edgeA"
                  value={this.state.edgeA}
                  onChange={this.handleChange}
                />

              Seite b:
                <input
                  type="text"
                  name="edgeB"
                  value={this.state.edgeB}
                  onChange={this.handleChange}
                />

          </form>

Flächeninhalt

          {this.state.area}

    );
  }
}

export default Rectangle;

Implement computation of rectangle's area


import React from 'react';

class ImageCardComponent extends React.Component {
  static propTypes = {
    uri: React.PropTypes.string.isRequired,
    uploadedAt: React.PropTypes.string.isRequired
  };

  render() {
    return (

            {this.props.uri}

              <time dateTime={this.props.uploadedAt}>{this.props.ploadedAt}</time>

    );
  }
}

export default ImageCardComponent;

import React from 'react';

class ImageCardComponent extends React.Component {
  static propTypes = {
    uri: React.PropTypes.string.isRequired,
    uploadedAt: React.PropTypes.string.isRequired
  };

  render() {
    return (

            {this.props.uri}

              <time dateTime={this.props.uploadedAt}>{this.props.uploadedAt}</time>

    );
  }
}

export default ImageCardComponent;

Fix typo 'ploadedAt' => 'uploadedAt'

Fix typo 'ploadedAt' => 'uploadedAt'


var canihaz = require('canihaz'),
  fs = require('fs'),
  p = require('path');

/**
 * Install dependency modules that are not yet installed, and needed for executing the tasks.
 *
 * @param {Array} depNames: an array of dependency module names
 * @param {String} dir: application directory where node_modules dir is located
 * @param {Function} cb: standard cb(err, result) callback
 */
function install(depNames, dir, cb) {
  fs.readdir(p.join(dir, 'node_modules'), function(err, installed) {
    var uninstalled = [];
    depNames.forEach(function (depName) {
      if (installed.indexOf(depName) === -1) {
        uninstalled.push(depName);
      }
    });
    if (uninstalled.length > 0) {
      console.log('[deps] Installing modules: %s (might take a while, once-off only)', uninstalled .join(', '));
      canihaz({ key: 'optDependencies' }).apply(this, depNames.concat(cb));
    } else {
      cb();
    }
  });
}

exports.install = install;

var canihaz = require('canihaz'),
  fs = require('fs'),
  p = require('path');

const GLOBALS = ['npm'];

/**
 * Install dependency modules that are not yet installed, and needed for executing the tasks.
 * Global modules (like npm) are assumed to already exist.
 *
 * @param {Array} depNames: an array of dependency module names
 * @param {String} dir: application directory where node_modules dir is located
 * @param {Function} cb: standard cb(err, result) callback
 */
function install(depNames, dir, cb) {
  fs.readdir(p.join(dir, 'node_modules'), function(err, installed) {
    var uninstalled = [];
    depNames.forEach(function (depName) {
      if (installed.indexOf(depName) === -1 && GLOBALS.indexOf(depName) === -1) {
        uninstalled.push(depName);
      }
    });
    if (uninstalled.length > 0) {
      console.log('[deps] Installing modules: %s (might take a while, once-off only)', uninstalled .join(', '));
      canihaz({ key: 'optDependencies' }).apply(this, depNames.concat(cb));
    } else {
      cb();
    }
  });
}

exports.install = install;

Add global modules list, to be excluded from lazy installation.